blob: c79d8b60fdf038b89dfada007b3e642f07eec2e4 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<title>Apache Jena - Jena Ontology API</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="/css/bootstrap-extension.css" rel="stylesheet" type="text/css">
<link href="/css/jena.css" rel="stylesheet" type="text/css">
<link rel="shortcut icon" href="/images/favicon.ico" />
<script src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script src="/js/jena-navigation.js" type="text/javascript"></script>
<script src="/js/bootstrap.min.js" type="text/javascript"></script>
<script src="/js/improve.js" type="text/javascript"></script>
</head>
<body>
<nav class="navbar navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/index.html">
<img class="logo-menu" src="/images/jena-logo/jena-logo-notext-small.png" alt="jena logo">Apache Jena</a>
</div>
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav">
<li id="homepage"><a href="/index.html"><span class="glyphicon glyphicon-home"></span> Home</a></li>
<li id="download"><a href="/download/index.cgi"><span class="glyphicon glyphicon-download-alt"></span> Download</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-book"></span> Learn <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="dropdown-header">Tutorials</li>
<li><a href="/tutorials/index.html">Overview</a></li>
<li><a href="/documentation/fuseki2/index.html">Fuseki Triplestore</a></li>
<li><a href="/documentation/notes/index.html">How-To's</a></li>
<li><a href="/documentation/query/manipulating_sparql_using_arq.html">Manipulating SPARQL using ARQ</a></li>
<li><a href="/tutorials/rdf_api.html">RDF core API tutorial</a></li>
<li><a href="/tutorials/sparql.html">SPARQL tutorial</a></li>
<li><a href="/tutorials/using_jena_with_eclipse.html">Using Jena with Eclipse</a></li>
<li class="divider"></li>
<li class="dropdown-header">References</li>
<li><a href="/documentation/index.html">Overview</a></li>
<li><a href="/documentation/query/index.html">ARQ (SPARQL)</a></li>
<li><a href="/documentation/assembler/index.html">Assembler</a></li>
<li><a href="/documentation/tools/index.html">Command-line tools</a></li>
<li><a href="/documentation/rdfs/">Data with RDFS Inferencing</a></li>
<li><a href="/documentation/geosparql/index.html">GeoSPARQL</a></li>
<li><a href="/documentation/inference/index.html">Inference API</a></li>
<li><a href="/documentation/javadoc.html">Javadoc</a></li>
<li><a href="/documentation/ontology/">Ontology API</a></li>
<li><a href="/documentation/permissions/index.html">Permissions</a></li>
<li><a href="/documentation/extras/querybuilder/index.html">Query Builder</a></li>
<li><a href="/documentation/rdf/index.html">RDF API</a></li>
<li><a href="/documentation/rdfconnection/">RDF Connection - SPARQL API</a></li>
<li><a href="/documentation/io/">RDF I/O</a></li>
<li><a href="/documentation/rdfstar/index.html">RDF-star</a></li>
<li><a href="/documentation/shacl/index.html">SHACL</a></li>
<li><a href="/documentation/shex/index.html">ShEx</a></li>
<li><a href="/documentation/jdbc/index.html">SPARQL over JDBC</a></li>
<li><a href="/documentation/tdb/index.html">TDB</a></li>
<li><a href="/documentation/tdb2/index.html">TDB2</a></li>
<li><a href="/documentation/query/text-query.html">Text Search</a></li>
</ul>
</li>
<li class="drop down">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-book"></span> Javadoc <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="/documentation/javadoc.html">All Javadoc</a></li>
<li><a href="/documentation/javadoc/arq/">ARQ</a></li>
<li><a href="/documentation/javadoc_elephas.html">Elephas</a></li>
<li><a href="/documentation/javadoc/fuseki2/">Fuseki</a></li>
<li><a href="/documentation/javadoc/geosparql/">GeoSPARQL</a></li>
<li><a href="/documentation/javadoc/jdbc/">JDBC</a></li>
<li><a href="/documentation/javadoc/jena/">Jena Core</a></li>
<li><a href="/documentation/javadoc/permissions/">Permissions</a></li>
<li><a href="/documentation/javadoc/extras/querybuilder/">Query Builder</a></li>
<li><a href="/documentation/javadoc/shacl/">SHACL</a></li>
<li><a href="/documentation/javadoc/tdb/">TDB</a></li>
<li><a href="/documentation/javadoc/text/">Text Search</a></li>
</ul>
</li>
<li id="ask"><a href="/help_and_support/index.html"><span class="glyphicon glyphicon-question-sign"></span> Ask</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-bullhorn"></span> Get involved <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="/getting_involved/index.html">Contribute</a></li>
<li><a href="/help_and_support/bugs_and_suggestions.html">Report a bug</a></li>
<li class="divider"></li>
<li class="dropdown-header">Project</li>
<li><a href="/about_jena/about.html">About Jena</a></li>
<li><a href="/about_jena/architecture.html">Architecture</a></li>
<li><a href="/about_jena/citing.html">Citing</a></li>
<li><a href="/about_jena/team.html">Project team</a></li>
<li><a href="/about_jena/contributions.html">Related projects</a></li>
<li><a href="/about_jena/roadmap.html">Roadmap</a></li>
<li class="divider"></li>
<li class="dropdown-header">ASF</li>
<li><a href="http://www.apache.org/">Apache Software Foundation</a></li>
<li><a href="http://www.apache.org/foundation/sponsorship.html">Become a Sponsor</a></li>
<li><a href="http://www.apache.org/licenses/LICENSE-2.0">License</a></li>
<li><a href="http://www.apache.org/security/">Security</a></li>
<li><a href="http://www.apache.org/foundation/thanks.html">Thanks</a></li>
</ul>
</li>
<li id="edit"><a href="https://github.com/apache/jena-site/edit/main/source/documentation/ontology/__index.md" title="Edit this page on GitHub"><span class="glyphicon glyphicon-pencil"></span> Edit this page</a></li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="breadcrumbs">
<ol class="breadcrumb">
<li><a href='/documentation'>DOCUMENTATION</a></li>
<li class="active">ONTOLOGY</li>
</ol>
</div>
<h1 class="title">Jena Ontology API</h1>
<p>This section is a general introduction to the Jena
ontology API, including some of the common tasks you may need
to perform. We
won&rsquo;t go into all of the many details of the API here: you should
expect to refer to the <a href="/documentation/javadoc/jena/">Javadoc</a> to
get full details of the capabilities of the API.</p>
<h3 id="prerequisites">Prerequisites</h3>
<p>We&rsquo;ll assume that you have a basic familiarity with RDF and with
Jena. If not, there are other
<a href="/getting_started">Jena help documents</a> you can read for background
on these topics, and a <a href="/tutorials">collection of tutorials</a>.</p>
<p>Jena is a programming toolkit, using the Java programming language.
While there are a few command-line tools to help you perform some
key tasks using Jena, mostly you use Jena by writing Java programs.
The examples in this document will be primarily code samples.</p>
<p>We also won&rsquo;t be explaining the OWL or RDFS ontology languages in
much detail in this document. You should refer to
supporting documentation for details on those languages, for
example the <a href="http://www.w3.org/2004/OWL/">W3C OWL document index</a>.</p>
<p><strong>Note:</strong> Although OWL version 1.1 is now a W3C recommendation,
Jena&rsquo;s support for OWL 1.1 features is limited. We will be addressing
this in future versions Jena.</p>
<h2 id="overview">Overview</h2>
<p>The section of the manual is broken into a number of sections. You
do not need to read them in sequence, though later sections may
refer to concepts and techniques introduced in earlier sections.
The sections are:</p>
<ul>
<li><a href="#general-concepts">General concepts</a></li>
<li><a href="#running-example-the-eswc-ontology">Running example: the ESWC ontology</a></li>
<li><a href="#creating-ontology-models">Creating ontology models</a></li>
<li><a href="#compound-ontology-documents-and-imports-processing">Compound ontology documents and imports processing</a></li>
<li><a href="#the-generic-ontology-type-ontresource">The generic ontology type: OntResource</a></li>
<li><a href="#ontology-classes-and-basic-class-expressions">Ontology classes and basic class expressions</a></li>
<li><a href="#ontology-properties">Ontology properties</a></li>
<li><a href="#more-complex-class-expressions">More complex class expressions</a></li>
<li><a href="#instances-or-individuals">Instances or individuals</a></li>
<li><a href="#ontology-meta-data">Ontology meta-data</a></li>
<li><a href="#ontology-inference-overview">Ontology inference: overview</a></li>
<li><a href="#working-with-persistent-ontologies">Working with persistent ontologies</a></li>
<li><a href="#experimental-ontology-tools">Experimental ontology tools</a></li>
</ul>
<h3 id="further-assistance">Further assistance</h3>
<p>Hopefully, this document will be sufficient to help most readers
to get started using the Jena ontology API. For further support,
please post questions to the <a href="/help_and_support">Jena support list</a>,
or <a href="/help_and_support/bugs_and_suggestions.html">file a bug report</a>.</p>
<p><em>Please note that we ask that you use the support list or the bug-tracker
to communicate with the Jena team, rather than send email to the team
members directly. This helps us manage Jena support more effectively,
and facilitates contributions from other Jena community members.</em></p>
<h2 id="general-concepts">General concepts</h2>
<p>In a widely-quoted definition, an ontology is</p>
<blockquote>
<p>&ldquo;a specification of a conceptualization&rdquo;
[<a href="https://web.archive.org/web/20160126114515/http://www-ksl.stanford.edu/kst/what-is-an-ontology.html">Gruber, T.</a> 1993]</p>
</blockquote>
<p>Let&rsquo;s unpack that brief characterisation a bit. An
ontology allows a programmer to specify, in an open, meaningful,
way, the concepts and relationships that collectively characterise
some domain of interest. Examples might be the concepts of red and white wine,
grape varieties, vintage years, wineries and so forth that
characterise the domain of &lsquo;wine&rsquo;, and relationships such as
&lsquo;wineries produce wines&rsquo;, &lsquo;wines have a year of production&rsquo;. This
<em>wine ontology</em> might be developed initially for a particular
application, such as a stock-control system at a wine warehouse. As
such, it may be considered similar to a well-defined database
schema. The advantage to an ontology is that it is an explicit,
first-class description. So having been developed for one purpose,
it can be published and reused for other purposes. For example, a
given winery may use the wine ontology to link its production
schedule to the stock system at the wine warehouse. Alternatively,
a wine recommendation program may use the wine ontology, and a
description (ontology) of different dishes to recommend wines for a
given menu.</p>
<p>There are many ways of writing down an ontology, and a variety of
opinions as to what kinds of definition should go in one. In
practice, the contents of an ontology are largely driven by the
kinds of application it will be used to support. In Jena, we do not
take a particular view on the minimal or necessary components of an
ontology. Rather, we try to support a variety of common techniques.
In this section, we try to explain what is – and to some extent what
isn&rsquo;t – possible using Jena&rsquo;s ontology support.</p>
<p>Since Jena is fundamentally an RDF platform, Jena&rsquo;s ontology
support is limited to ontology formalisms built on top of RDF.
Specifically this means <a href="http://en.wikipedia.org/wiki/RDFS">RDFS</a>,
the varieties of
<a href="http://en.wikipedia.org/wiki/Web_Ontology_Language">OWL</a>.
We will provide a very brief introduction to these languages here,
but please refer to the extensive on-line documentation for these
formalisms for complete and authoritative details.</p>
<h3 id="rdfs">RDFS</h3>
<p>RDFS is the weakest ontology language supported by Jena. RDFS
allows the ontologist to build a simple hierarchy of concepts, and
a hierarchy of properties. Consider the following trivial
characterisation (with apologies to biology-trained readers!):</p>
<p><img src="simple-hierarchy.png" alt="image of simple class hierarchy" title="Table 1: A simple concept hierarchy">
<br />Table 1: A simple concept hierarchy</p>
<p>Using RDFS, we can say that my ontology has five <em>classes</em>, and that
<code>Plant</code> is a <em>sub-class of</em> <code>Organism</code> and so on. So every animal
is also an organism. A good way to think of these classes is as
describing sets of <em>individuals</em>: organism is intended to describe
a set of living things, some of which are animals (i.e. a sub-set
of the set of organisms is the set of animals), and some animals
are fish (a subset of the set of all animals is the set of all
fish).</p>
<p>To describe the attributes of these classes, we can associate
<em>properties</em> with the classes. For example, animals have sensory
organs (noses, eyes, etc.). A general property of an animal might
be <code>senseOrgan</code>, to denote any given sensory organs a particular
animal has. In general, fish have eyes, so a fish might have a
<code>eyes</code> property to refer to a description of the particular eye
structure of some species. Since eyes are a type of sensory organ,
we can capture this relationship between these properties by saying
that <code>eye</code> is a sub-property-of <code>senseOrgan</code>. Thus if a given fish
has two eyes, it also has two sense organs. (It may have more, but
we know that it must have two).</p>
<p>We can describe this simple hierarchy with RDFS. In general, the
class hierarchy is a graph rather than a tree (i.e. not like Java
class inheritance). The
<a href="http://en.wikipedia.org/wiki/Slime_mold">slime mold</a> is popularly,
though perhaps not accurately, thought of as an organism that has
characteristics of both plants and animals. We might model a slime
mold in our ontology as a class that has both plant and animal
classes among its super-classes. RDFS is too weak a language to
express the constraint that a thing cannot be both a plant and an animal (which is
perhaps lucky for the slime molds). In RDFS, we can only name the
classes, we cannot construct expressions to describe interesting
classes. However, for many applications it is sufficient to state
the basic vocabulary, and RDFS is perfectly well suited to this.</p>
<p>Note also that we can both describe classes, in general terms, and we
can describe particular <em>instances</em> of those classes. So there may
be a particular individual Fred who is a Fish (i.e. has
<code>rdf:type Fish</code>), and who has two eyes. Their companion Freda, a
<a href="http://en.wikipedia.org/wiki/Mexican_tetra">Mexican Tetra</a>, or
blind cave fish, has no eyes. One use of an ontology is to allow us
to fill-in missing information about individuals. Thus, though it
is not stated directly, we can deduce that Fred is also an Animal
and an Organism. Assume that there was no <code>rdf:type</code> asserting that
Freda is a Fish. We may still infer Freda&rsquo;s <code>rdf:type</code> since Freda
has <a href="http://en.wikipedia.org/wiki/Lateral_line">lateral lines</a> as
sense organs, and these only occur in fish. In RDFS, we state that
the <em>domain</em> of the <code>lateralLines</code> property is the <code>Fish</code> class, so
an RDFS reasoner can infer that Freda must be a fish.</p>
<h3 id="owl">OWL</h3>
<p>In general, OWL allows us to say everything that RDFS allows, and
much more besides. A key part of OWL is the ability to describe
classes in more interesting and complex ways. For example, in OWL
we can say that Plant and Animal are <em>disjoint classes</em>: no
individual can be both a plant and an animal (which would have the
unfortunate consequence of making <code>SlimeMold</code> an empty class).
<code>SaltwaterFish</code> might be the <em>intersection</em> of <code>Fish</code> and the class
<code>SeaDwellers</code> (which also includes, for example, cetaceans and sea
plants).</p>
<p>Suppose we have a property <code>covering</code>, intended to represent the
scales of a fish or the fur of a mammal. We can now refine the
mammal class to be &lsquo;animals that have a covering that is hair&rsquo;,
using a <em>property restriction</em> to express the condition that
property <code>covering</code> has a value from the class <code>Hair</code>. Similarly
<code>TropicalFish</code> might be the intersection of the class of <code>Fish</code> and
the class of things that have <code>TropicalOcean</code> as their habitat.</p>
<p>Finally (for this brief overview), we can say more about properties
in OWL. In RDFS, properties can be related via a property
hierarchy. OWL extends this by allowing properties to be denoted as
<em>transitive</em>, <em>symmetric</em> or <em>functional</em>, and allow one property
to be declared to be the <em>inverse</em> of another. OWL also makes a
distinction between properties that have individuals (RDF resources)
as their range and properties that have data-values (known as
<em>literals</em> in RDF terminology) as their range.
Respectively these are <em>object properties</em> and <em>datatype properties</em>.
One consequence of the RDF lineage of OWL is
that OWL ontologies cannot make statements about literal values. We
cannot say in RDF that <code>seven</code> has the property of being a prime number.
We can, of course, say that the class of primes includes seven, doing so
doesn&rsquo;t require a number to be the subject of an RDF statement. In
OWL, this distinction is important: only object properties can
be transitive or symmetric.</p>
<p>The OWL language is sub-divided into three syntax classes:
<em>OWL Lite</em>, <em>OWL DL</em> and <em>OWL Full</em>. OWL DL does not permit some
constructions allowed in OWL Full, and OWL Lite has all the
constraints of OWL DL plus some more. The intent for OWL Lite and
OWL DL is to make the task of reasoning with expressions in that
subset more tractable. Specifically, OWL DL is intended to be able
to be processed efficiently by a
<a href="http://en.wikipedia.org/wiki/Description_logic"><em>description logic</em></a>
reasoner. OWL Lite is intended to be amenable to processing by a
variety of reasonably simple inference algorithms, though experts
in the field have challenged how successfully this has been
achieved.</p>
<p>While the OWL standards documents note that OWL builds on top of
the (revised) RDF specifications, it is possible to treat OWL as a
separate language in its own right, and not something that is built
on an RDF foundation. This view uses RDF as a serialisation syntax;
the RDF-centric view treats RDF triples as the core of the OWL
formalism. While both views are valid, in Jena we take the
RDF-centric view.</p>
<h3 id="ontology-languages-and-the-jena-ontology-api">Ontology languages and the Jena Ontology API</h3>
<p>As we outlined above, there are various different ontology languages
available for representing ontology information on the semantic
web. They range from the most expressive, OWL Full, through to the
weakest, RDFS. Through the Ontology API, Jena aims to provide a
consistent programming interface for ontology application
development, independent of which ontology language you are using
in your programs.</p>
<p>The Jena Ontology API is language-neutral: the Java class names are not
specific to the underlying language. For example, the <code>OntClass</code>
Java class can represent an OWL class or RDFS class.
To represent the differences between the various representations,
each of the ontology languages has a <em>profile</em>, which lists the
permitted constructs and the names of the classes and properties.</p>
<p>Thus in the OWL profile is it <code>owl:ObjectProperty</code> (short for
<code>http://www.w3.org/2002/07/owl#ObjectProperty</code>) and in the RDFS
profile it is <code>null</code> since RDFS does not define object properties.</p>
<p>The profile is bound to an <em>ontology model</em>, which is an extended
version of Jena&rsquo;s
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/Model.html"><code>Model</code></a> class.
The base <code>Model</code> allows access to the statements in a collection of
RDF data.
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/OntModel.html"><code>OntModel</code></a>
extends this by adding support for the kinds of constructs expected to
be in an ontology: classes (in a class hierarchy), properties (in a
property hierarchy) and individuals.</p>
<p>When you&rsquo;re working with an
ontology in Jena, all of the state information remains encoded as
RDF triples (accessed as Jena
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/Statement.html"><code>Statement</code>s</a>) stored in the RDF
model. The ontology API
doesn&rsquo;t change the RDF representation of ontologies. What it does
do is add a set of convenience classes and methods that make it
easier for you to write programs that manipulate the underlying RDF
triples.</p>
<p>The predicate names defined in the ontology language correspond to
the accessor methods on the Java classes in the API. For example,
an <code>OntClass</code> has a method to list its super-classes, which
corresponds to the values of the <code>subClassOf</code> property in the RDF
representation. This point is worth re-emphasising: no information
is stored in the <code>OntClass</code> object itself. When you call the
OntClass <code>listSuperClasses()</code> method, Jena will retrieve the
information from the underlying RDF triples. Similarly, adding a
subclass to an <code>OntClass</code> asserts an additional RDF triple, typically
with predicate <code>rdfs:subClassOf</code> into
the model.</p>
<h3 id="ontologies-and-reasoning">Ontologies and reasoning</h3>
<p>One of the key benefits of building an ontology-based application
is using a reasoner to derive additional truths about the concepts
you are modelling. We saw a simple instance of this above: the
assertion &ldquo;Fred is a Fish&rdquo; <em>entails</em> the deduction &ldquo;Fred is an
Animal&rdquo;. There are many different styles of automated reasoner, and
very many different reasoning algorithms. Jena includes support for
a variety of reasoners through the
<a href="../inference">inference API</a>.</p>
<p>A common feature of Jena
reasoners is that they create a new RDF model which appears to
contain the triples that are derived from reasoning as well as the
triples that were asserted in the base model. This extended model
nevertheless still conforms to the contract for Jena models.
It can be used wherever a non-inference model can be used. The ontology
API exploits this feature: the convenience methods provide by the ontology API
can query an extended inference model in just the same way
that they can a plain RDF model. In fact, this is such a common pattern that
we provide simple recipes for constructing ontology models whose
language, storage model and reasoning engine can all be simply
specified when an <code>OntModel</code> is created. We&rsquo;ll show examples shortly.</p>
<p>Figure 2 shows one way of visualising this:</p>
<p><img src="ont-model-layers.png" alt="image of layering of graphs in model" title="Figure 2: the statements seen by the OntModel"></p>
<p><code>Graph</code> is an internal Jena interface that supports the composition
of sets of RDF triples. The asserted statements, which may have
been read in from an ontology document, are held in the base graph.
The reasoner, or inference engine, can use the contents of the base
graph and the semantic rules of the language to show a more
complete set of base and entailed triples. This is also presented via a <code>Graph</code>
interface, so the <code>OntModel</code> works only with the outermost interface.
This regularity allows us to very easily build ontology models with
or without a reasoner. It also means that the base graph can be an
in-memory store, a database-backed persistent store, or some other
storage structure altogether – e.g. an LDAP directory – again without
affecting the operation of the ontology model (but noting that these
different approaches may have very different efficiency profiles).</p>
<h3 id="rdf-level-polymorphism-and-java">RDF-level polymorphism and Java</h3>
<p>Deciding which Java abstract class to use to represent a given RDF
resource can be surprisingly subtle. Consider the following RDF
sample:</p>
<pre><code>&lt;owl:Class rdf:ID=&quot;DigitalCamera&quot;&gt;
&lt;/owl:Class&gt;
</code></pre>
<p>This declares that the resource with the relative URI
<code>#DigitalCamera</code> is an OWL ontology class. It suggests that it
would be appropriate to model that declaration in Java with an
instance of an <code>OntClass</code>. Now suppose we add a triple to the RDF
model to augment the class declaration with some more information:</p>
<pre><code>&lt;owl:Class rdf:ID=&quot;DigitalCamera&quot;&gt;
&lt;rdf:type owl:Restriction /&gt;
&lt;/owl:Class&gt;
</code></pre>
<p>Now we are stating that <code>#DigitalCamera</code> is an OWL Restriction.
Restriction is a subclass of <code>owl:Class</code>, so this is a perfectly
consistent operation. The problem we then have is that Java does not
allow us to dynamically change the Java class of the object
representing this resource. The resource has not changed: it still
has URI <code>#DigitalCamera</code>. But the appropriate Java class Jena might
choose to encapsulate it has changed from <code>OntClass</code> to <code>Restriction</code>.
Conversely, if we subsequently remove the <code>rdf:type owl:Restriction</code>
from the model, using the <code>Restriction</code> Java class is no longer
appropriate.</p>
<p>Even worse, OWL Full allows us to state the following (rather
counter-intuitive) construction:</p>
<pre><code>&lt;owl:Class rdf:ID=&quot;DigitalCamera&quot;&gt;
&lt;rdf:type owl:ObjectProperty /&gt;
&lt;/owl:Class&gt;
</code></pre>
<p>That is, <code>#DigitalCamera</code> is both a class <em>and</em> a property. While
this may not be a very useful claim, it illustrates a basic
point: we cannot rely on a consistent or unique mapping between an
RDF resource and the appropriate Java abstraction.</p>
<p>Jena accepts this basic characteristic of polymorphism at the RDF
level by considering that the Java abstraction (<code>OntClass</code>,
<code>Restriction</code>, <code>DatatypeProperty</code>, etc.) is just a view or <em>facet</em>
of the resource. That is, there is a one-to-many mapping from a
resource to the facets that the resource can present. If the
resource is typed as an <code>owl:Class</code>, it can present the <code>OntClass</code>
facet; given other types, it can present other facets. Jena
provides the <code>.as()</code> method to efficiently map from an RDF object
to one of its allowable facets. Given a RDF object (i.e. an
instance of <code>org.apache.jena.rdf.model.RDFNode</code> or one of its
sub-types), you can get a facet by invoking <code>as()</code> with an argument
that denotes the facet required. Specifically, the facet is
identified by the Java class object of the desired facet. For
example, to get the <code>OntClass</code> facet of a resource, we can write:</p>
<pre><code>Resource r = myModel.getResource( myNS + &quot;DigitalCamera&quot; );
OntClass cls = r.as( OntClass.class );
</code></pre>
<p>This pattern allows our code to defer decisions about the correct Java
abstraction to use until run-time. The choice can depend on the
properties of the resource itself. If a given <code>RDFNode</code> will not
support the conversion to a given facet, it will raise a
<code>ConversionException</code>. We can test whether <code>.as()</code> will succeed for a
given facet with <code>canAs()</code>. This RDF-level polymorphism is used
extensively in the Jena ontology API to allow maximum flexibility
in handling ontology data.</p>
<h2 id="running-example-the-eswc-ontology">Running example: the ESWC ontology</h2>
<p>To illustrate the principles of using the ontology API, we will use
examples drawn from the
<a href="http://data.semanticweb.org/ns/swc/swc_2009-05-09.html">ESWC ontology</a>
This ontology presents a simple model for describing the concepts
and activities associated with a typical academic conference. A
copy of the ontology serialized in RDF/XML is included with the
Jena download, see:
[<a href="https://raw.githubusercontent.com/apache/jena/main/jena-core/src-examples/data/eswc-2006-09-21.rdf"><code>eswc-2006-09-21.rdf</code></a>]
(note that you may need to view the page source in some browsers to
see the XML code).</p>
<p>A subset of the classes and properties from the ontology are shown
in Figure 3:</p>
<p><img src="eswc-classes.png" alt="Image of the example class hierarchy" title="Figure 3: Classes and properties from ESWC ontology">
<br />Figure 3: Classes and properties from ESWC ontology</p>
<p>We will use elements from this ontology to illustrate the ontology
API throughout the rest of this document.</p>
<h2 id="creating-ontology-models">Creating ontology models</h2>
<p>An ontology model is an extension of the Jena RDF model,
providing extra capabilities for handling ontologies. Ontology
models are created through the Jena
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/ModelFactory.html"><code>ModelFactory</code></a>.
The simplest way to create an ontology model is as follows:</p>
<pre><code>OntModel m = ModelFactory.createOntologyModel();
</code></pre>
<p>This will create an ontology model with the <em>default</em> settings,
which are set for maximum compatibility with the previous version
of Jena. These defaults are:</p>
<ul>
<li>OWL-Full language</li>
<li>in-memory storage</li>
<li>RDFS inference, which principally produces entailments from the
sub-class and sub-property hierarchies.</li>
</ul>
<p><strong>Important note</strong>: this means that the <em>default ontology model</em> <strong>does</strong>
include some inferencing, with consequences both for the performance of the
model, and for the triples which appear in the model.</p>
<p>In many applications, such as driving a GUI, RDFS inference is too
strong. For example, every class is inferred to be an immediate sub-class of
<code>owl:Thing</code>. In other applications, stronger reasoning is needed.
In general, to create an <code>OntModel</code> with a particular reasoner or
language profile, you should pass a model specification to the
<code>createOntologyModel</code> call. For example, an OWL model that performs
no reasoning at all can be created with:</p>
<pre><code>OntModel m = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM );
</code></pre>
<p>To create an ontology model for a particular language, but leaving
all of the other values as defaults, you should pass the URI of the
ontology language to the model factory. The URI strings for the
various language profiles are:</p>
<table>
<thead>
<tr>
<th>Ontology language</th>
<th>URI</th>
</tr>
</thead>
<tbody>
<tr>
<td>RDFS</td>
<td><code>http://www.w3.org/2000/01/rdf-schema#</code></td>
</tr>
<tr>
<td>OWL Full</td>
<td><code>http://www.w3.org/2002/07/owl#</code></td>
</tr>
<tr>
<td>OWL DL</td>
<td><code>http://www.w3.org/TR/owl-features/#term_OWLDL</code></td>
</tr>
<tr>
<td>OWL Lite</td>
<td><code>http://www.w3.org/TR/owl-features/#term_OWLLite</code></td>
</tr>
</tbody>
</table>
<p>These URI&rsquo;s are used to look-up the language profile from the
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/ProfileRegistry.html"><code>ProfileRegistry</code></a>.
The profile registry contains public constant declarations so
that you do not have to remember these URI&rsquo;s. Please note that the
URI&rsquo;s denoting OWL Lite and OWL DL are not officially sanctioned by
the OWL standard.</p>
<p>Beyond these basic choices, the complexities of configuring an
ontology model are wrapped up in a recipe object called
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/OntModelSpec.html"><code>OntModelSpec</code></a>.
This specification allows complete control over the configuration
choices for the ontology model, including the language profile in
use, the reasoner, and the means of handling compound documents. A
number of common recipes are pre-declared as constants in
<code>OntModelSpec</code>, and listed below.</p>
<table>
<thead>
<tr>
<th>OntModelSpec</th>
<th>Language profile</th>
<th>Storage model</th>
<th>Reasoner</th>
</tr>
</thead>
<tbody>
<tr>
<td>OWL_MEM</td>
<td>OWL full</td>
<td>in-memory</td>
<td>none</td>
</tr>
<tr>
<td>OWL_MEM_TRANS_INF</td>
<td>OWL full</td>
<td>in-memory</td>
<td>transitive class-hierarchy inference</td>
</tr>
<tr>
<td>OWL_MEM_RULE_INF</td>
<td>OWL full</td>
<td>in-memory</td>
<td>rule-based reasoner with OWL rules</td>
</tr>
<tr>
<td>OWL_MEM_MICRO_RULE_INF</td>
<td>OWL full</td>
<td>in-memory</td>
<td>optimised rule-based reasoner with OWL rules</td>
</tr>
<tr>
<td>OWL_MEM_MINI_RULE_INF</td>
<td>OWL full</td>
<td>in-memory</td>
<td>rule-based reasoner with subset of OWL rules</td>
</tr>
<tr>
<td>OWL_DL_MEM</td>
<td>OWL DL</td>
<td>in-memory</td>
<td>none</td>
</tr>
<tr>
<td>OWL_DL_MEM_RDFS_INF</td>
<td>OWL DL</td>
<td>in-memory</td>
<td>rule reasoner with RDFS-level entailment-rules</td>
</tr>
<tr>
<td>OWL_DL_MEM_TRANS_INF</td>
<td>OWL DL</td>
<td>in-memory</td>
<td>transitive class-hierarchy inference</td>
</tr>
<tr>
<td>OWL_DL_MEM_RULE_INF</td>
<td>OWL DL</td>
<td>in-memory</td>
<td>rule-based reasoner with OWL rules</td>
</tr>
<tr>
<td>OWL_LITE_MEM</td>
<td>OWL Lite</td>
<td>in-memory</td>
<td>none</td>
</tr>
<tr>
<td>OWL_LITE_MEM_TRANS_INF</td>
<td>OWL Lite</td>
<td>in-memory</td>
<td>transitive class-hierarchy inference</td>
</tr>
<tr>
<td>OWL_LITE_MEM_RDFS_INF</td>
<td>OWL Lite</td>
<td>in-memory</td>
<td>rule reasoner with RDFS-level entailment-rules</td>
</tr>
<tr>
<td>OWL_LITE_MEM_RULES_INF</td>
<td>OWL Lite</td>
<td>in-memory</td>
<td>rule-based reasoner with OWL rules</td>
</tr>
<tr>
<td>RDFS_MEM</td>
<td>RDFS</td>
<td>in-memory</td>
<td>none</td>
</tr>
<tr>
<td>RDFS_MEM_TRANS_INF</td>
<td>RDFS</td>
<td>in-memory</td>
<td>transitive class-hierarchy inference</td>
</tr>
<tr>
<td>RDFS_MEM_RDFS_INF</td>
<td>RDFS</td>
<td>in-memory</td>
<td>rule reasoner with RDFS-level entailment-rules</td>
</tr>
</tbody>
</table>
<p>For details of reasoner capabilities, please see the
<a href="../inference">inference documentation</a> and the Javadoc
for
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/OntModelSpec.html">OntModelSpec</a>.
See also further discussion <a href="#inference-intro">below</a>.</p>
<p><strong>Note:</strong> it is primarily the choice of reasoner, rather than the
choice of language profile, which determines which entailments are
seen by the ontology model.</p>
<p>To create a model with a given specification, you should invoke the
<code>ModelFactory</code> as follows:</p>
<pre><code>OntModel m = ModelFactory.createOntologyModel( &lt;model spec&gt; );
</code></pre>
<p>for example:</p>
<pre><code>OntModel m = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM_MICRO_RULE_INF );
</code></pre>
<p>To create a custom model specification, you can create a new one
from its constructor, and call the various setter methods to set
the appropriate values. More often, we want a variation on an
existing recipe. In this case, you copy an existing specification
and then update the copy as necessary:</p>
<pre><code>OntModelSpec s = new OntModelSpec( OntModelSpec.OWL_MEM );
s.setDocumentManager( myDocMgr );
OntModel m = ModelFactory.createOntologyModel( s );
</code></pre>
<h2 id="compound-ontology-documents-and-imports-processing">Compound ontology documents and imports processing</h2>
<p>The OWL ontology language includes some facilities for
creating modular ontologies that can be re-used in a similar manner
to software modules. In particular, one ontology can <em>import</em>
another. Jena helps ontology developers to work with modular
ontologies by automatically handling the imports statements in
ontology models.</p>
<p>The key idea is that the base model of an ontology model is
actually a collection of models, one per imported model. This means
we have to modify figure 2 a bit. Figure 4 shows how the ontology
model builds a collection of import models:</p>
<p><img src="./ont-model-layers-import.png" alt="Diagram of compound document for imports" title="ontology model compound document structure for imports">
<br />
Figure 4: ontology model compound document structure for imports</p>
<p>We will use the term <em>document</em> to describe an ontology serialized
in some transport syntax, such as RDF/XML or N3. This terminology
isn&rsquo;t used by the OWL or RDFS standards, but it is a convenient way
to refer to the written artifacts. However, from a broad view of
the interlinked semantic web, a document view imposes artificial
boundaries between regions of the global web of data and isn&rsquo;t necessarily
a useful way of thinking about ontologies.</p>
<p>We will load an ontology document into an ontology model in the
same way as a normal Jena model, using the <code>read</code> method. There are
several variants on read, that handle differences in the source of
the document (to be read from a resolvable URL or directly from an
input stream or reader), the base URI that will resolve any
relative URI&rsquo;s in the source document, and the serialisation
language. In summary, these variants are:</p>
<pre><code>read( String url )
read( Reader reader, String base )
read( InputStream reader, String base )
read( String url, String lang )
read( Reader reader, String base, String Lang )
read( InputStream reader, String base, String Lang )
</code></pre>
<p>You can use any of these methods to load an ontology document. Note
that we advise that you avoid the <code>read()</code> variants that accept
a <code>java.io.Reader</code> argument when loading XML documents containing
internationalised character sets, since the handling of character
encoding by the Reader and by XML parsers is not compatible.</p>
<p>By default, when an ontology model reads an ontology document, it
will also locate and load the document&rsquo;s imports. An OWL
document may contain an individual of class <code>Ontology</code>, which
contains meta-data about that document itself. For example:</p>
<pre><code>&lt;owl:Ontology rdf:about=&quot;&quot;&gt;
&lt;dc:creator rdf:value=&quot;Ian Dickinson&quot; /&gt;
&lt;owl:imports rdf:resource=&quot;http://jena.apache.org/examples/example-ont&quot; /&gt;
&lt;/owl:Ontology&gt;
</code></pre>
<p>The construct <code>rdf:about=&quot;&quot;</code> is a <em>relative URI</em>. It will resolve to
the document&rsquo;s base URI: in other words it&rsquo;s a shorthand way of
referring to the document itself. The <code>owl:imports</code> line states
that this ontology is constructed using classes, properties and
individuals from the referenced ontology. When an <code>OntModel</code> reads
this document, it will notice the <code>owl:imports</code> line and attempt to
load the imported ontology into a sub-model of the ontology model
being constructed. The definitions from both the base ontology and all of
the imports will be visible to the reasoner.</p>
<p>Each imported ontology document is held in a separate graph
structure. This is important: we want to keep the original source
ontology separate from the imports. When we write the model out
again, normally only the base model is written (the alternative is
that all you see is a confusing union of everything). And when we
update the model, only the base model changes. To get the base
model or base graph from an <code>OntModel</code>, use:</p>
<pre><code>Model base = myOntModel.getBaseModel();
</code></pre>
<p>Imports are processed recursively, so if our base document imports
ontology A, and A imports B, we will end up with the structure shown
in Figure 4. Note that the imports have been flattened out. A cycle
check is used to prevent the document handler getting stuck if, for
example, A imports B which imports A!</p>
<h3 id="the-ontology-document-manager">The ontology document manager</h3>
<p>Each ontology model has an associated <em>document manager</em> which
assists with the processing and handling of ontology documents and related
concerns. For convenience, there is one global document manager
which is used by default by ontology models. You can get a reference
to this shared instance through <code>OntDocumentManager.getInstance()</code>.
In many cases, it will be sufficient to simply change the settings
on the global document manager to suit your application&rsquo;s needs.
However, for more fine-grain control, you can create separate
document managers, and pass them to the ontology model when it is
created through the model factory. To do this, create an ontology
specification object (see above), and set the document manager. For
example:</p>
<pre><code>OntDocumentManager mgr = new OntDocumentManager();
// set mgr's properties now
... some code ...
// now use it
OntModelSpec s = new OntModelSpec( OntModelSpec.RDFS_MEM );
s.setDocumentManager( mgr );
OntModel m = ModelFactory.createOntologyModel( s );
</code></pre>
<p>Note that the model retains a reference to the document manager it
was created with. Thus if you change a document manager&rsquo;s
properties, it will affect models that have previously been
constructed with that document manager.</p>
<h3 id="document-manager-policy">Document manager policy</h3>
<p>Since the document manager has a large number of configurable
options, there are two ways in which you can customise it to your
application requirements. Firstly, you can set the individual
parameters of the document manager by Java code. Alternatively,
when a given document manager is created it can load values for the
various parameters from a <em>policy file</em>, expressed in RDF. The
document manager has a list of URL&rsquo;s which it will search for a
policy document. It will stop at the first entry on the list that
resolves to a retrievable document. The default search path for the
policy is: <code>file:./etc/ont-policy.rdf;file:ont-policy.rdf</code>. You can
find the default policy, which can serve as a template for defining
your own policies, in the <code>etc/</code> directory under the Jena download
directory.</p>
<p>We can set the general properties of the document manager in the
policy as follows:</p>
<pre><code>&lt;DocumentManagerPolicy&gt;
&lt;!-- policy for controlling the document manager's behaviour --&gt;
&lt;processImports rdf:datatype=&quot;&amp;xsd;boolean&quot;&gt;true&lt;/processImports&gt;
&lt;cacheModels rdf:datatype=&quot;&amp;xsd;boolean&quot;&gt;true&lt;/cacheModels&gt;
&lt;/DocumentManagerPolicy&gt;
</code></pre>
<p>You can find the simple schema that declares the various properties
that you can use in such an ontology document policy in the
<code>vocabularies</code> directory of the Jena download. It&rsquo;s called
<code>ont-manager.rdf</code>. To change the search path that the document
manager will use to initialise itself, you can either pass the new
search path as a string when creating a new document manager
object, or call the method <code>setMetadataSearchPath()</code>.</p>
<h3 id="the-modelmaker-creating-storage-on-demand">The ModelMaker: creating storage on demand</h3>
<p>In order for the document manager to build the union of the
imported documents (which we sometimes refer to as the
<em>imports closure</em>), there must be some means of creating new graphs
to store the imported ontologies. Loading a new import means that
a new graph needs to be added. Jena defines a <em>model maker</em> as
a simple interface that allows different kinds of model storage
(in-memory, file-backed, in a persistent database, etc.) to be created
on demand. For the database case, this may include passing the
database user-name and password and other connection parameters.
New model makers can be created with the
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/ModelFactory.html"><code>ModelFactory</code></a>.</p>
<p>There are two cases in which we may want to create storage for
models on-demand. The first is when creating the <code>OntModel</code> for the
first time. Some variants of <code>createOntologyModel</code> will allocate
space for the <em>base model</em> (instead of, for example, being handed a
base model to use as one of the method arguments). The second case
when storage must be allocated is when adding an imported document
to the union of imports. These cases often require different
policies, so the <code>OntModelSpec</code> contains <em>two</em> model maker
parameters: the <em>base model maker</em> and <em>imports model maker</em>,
available via <code>getBaseModelMaker()</code> and <code>getImportsModelMaker()</code>
methods respectively.</p>
<p>The default specifications in OntModelSpec which begin MEM_ use an
in-memory model maker for the both the base model and the imported
documents.</p>
<p><strong>Implementation note</strong>: internally to Jena, we use <code>Graph</code> as a
primary data structure. However, application code will almost always refer
to models, not graphs. What&rsquo;s happening is that a <code>Model</code> is a
wrapper around the <code>Graph</code>, which balances a rich, convenient
programming interface (<code>Model</code>) with a simple, manageable internal
data structure (<code>Graph</code>). Hence some potential confusion in that
Figure 4, above, refers to a structure containing graphs, but we
use a
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/ModelMaker.html"><code>ModelMaker</code></a>
to generate new stores. The document manager extracts the
appropriate graph from the containing model. Except in cases where
you are extending Jena&rsquo;s internal structures, you should think of
<code>Model</code> as the container of RDF and ontology data.</p>
<h3 id="controlling-imports-processing">Controlling imports processing</h3>
<p>By default, loading imports during the <code>read()</code> call is automatic. To
<code>read()</code> an ontology without building the imports closure, call the
method <code>setProcessImports( false )</code> on the document manager object
before calling <code>read()</code>. Alternatively, you can set the
<code>processImports</code> property in the policy file. You can also be more
selective, and ignore only certain URI&rsquo;s when loading the imported
documents. To selectively skip certain named imports, call the
method <code>addIgnoreImport( String uri )</code> on the document manager
object, or set the <code>ignoreImport</code> property in the policy.</p>
<h3 id="managing-file-references">Managing file references</h3>
<p>An advantage of working with ontologies is that we can reuse work
done by other ontologists, by importing their published ontologies
into our own. The <code>OntModel</code> can load such referenced ontologies
automatically from their published URL&rsquo;s. This can mean that an
application suffers a delay on startup. Worse, it may require extra
work to cope with intervening firewalls or web proxies. Worse still,
connectivity may be intermittent: we do not want our application to
fail just because it temporarily does not have Internet access, or
because a previously published ontology has been moved.
To alleviate these commonly
experienced problems, we can use Jena&rsquo;s
<a href="/documentation/javadoc/jena/org/apache/jena/util/FileManager.html"><code>FileManager</code></a> to
manage local indirections, so that an attempt to import a
document from a given published URL means that a local copy of the
document is loaded instead. This may be a file on the local disk, or simply a
pointer to a local mirror web site.</p>
<p>While the <code>FileManager</code> can be configured directly, we can also specify redirections
declaratively in the document manager policy file:</p>
<pre><code>&lt;OntologySpec&gt;
&lt;publicURI rdf:resource=&quot;... the public URI to map from...&quot; /&gt;
&lt;altURL rdf:resource=&quot;... the local URL to map to ...&quot; /&gt;
&lt;!-- optional ontology language term --&gt;
&lt;language rdf:resource=&quot;... encoding used ...&quot; /&gt;
&lt;!-- optional prefix to associate with the public URL --&gt;
&lt;prefix rdf:datatype=&quot;&amp;xsd;string&quot;&gt;a prefix&lt;/prefix&gt;
&lt;/OntologySpec&gt;
</code></pre>
<p>For example:</p>
<pre><code>&lt;OntologySpec&gt;
&lt;!-- local version of the RDFS vocabulary --&gt;
&lt;publicURI rdf:resource=&quot;http://www.w3.org/2000/01/rdf-schema&quot; /&gt;
&lt;altURL rdf:resource=&quot;file:src/main/resources/rdf-schema.rdf&quot; /&gt;
&lt;/OntologySpec&gt;
</code></pre>
<p>This specifies that an attempt to load the RDFS vocabulary from
<code>http://www.w3.org/2000/01/rdf-schema</code> will transparently cause
<code>file:src/main/resources/rdf-schema.rdf</code> to be fetched instead. You can
specify any number of such re-directions in the policy file, or you
can add them to the document manager object directly by calling the
various setter methods (see the Javadoc for details). As a
side-effect, this mechanism also means that ontologies may be named
with any legal URI (not necessarily resolvable) – so long as the
<code>altURL</code> is itself resolvable.</p>
<p>See the notes on
<a href="/documentation/javadoc/jena/org/apache/jena/util/FileManager.html"><code>FileManager</code></a> for details of additional options.</p>
<p>In the following example, we use the <code>DocumentManager</code> API to declare that the ESWC
ontology is replicated locally on disk. We then load it using
the normal URL. Assume that the constant <code>JENA</code> has been
initialised to the directory in which Jena was installed.</p>
<pre><code>OntModel m = ModelFactory.createOntologyModel();
OntDocumentManager dm = m.getDocumentManager();
dm.addAltEntry( &quot;http://www.eswc2006.org/technologies/ontology&quot;,
&quot;file:&quot; + JENA + &quot;src/examples/resources/eswc-2006-09-21.rdf&quot; );
m.read( &quot;http://www.eswc2006.org/technologies/ontology&quot; );
</code></pre>
<h3 id="specifying-prefixes">Specifying prefixes</h3>
<p>A model keeps a table of URI prefixes which can be used to present
URI&rsquo;s in the shortened <code>prefix:name</code> form. This is useful in
displaying URI&rsquo;s in a readable way in user interfaces, and is
essential in producing legal XML names that denote arbitrary URI&rsquo;s.
The ontology model&rsquo;s table of prefixes can be initialized from a
table kept by the document manager, which contains the standard
prefixes plus any that are declared by in the policy file (or added
to subsequently by method calls).</p>
<h3 id="caching-of-imported-models">Caching of imported models</h3>
<p>You can use the document manager to assist with loading ontology
documents through its cache. Suppose two ontologies, A and B, both
import ontology C. We would like not to have to read C twice when
loading A and then B. The document manager supports this use case
by optionally caching C&rsquo;s model, indexed by URI. When A tries to
import C, there is no cached copy, so a new model is created for C,
the contents of C&rsquo;s URL read in to the model, then the C model is
used in the compound document for A. Subsequently, when ontology B
is loading imports, the document manager checks in its cache and
finds an existing copy of C. This will be used in preference to
reading a fresh copy of C from C&rsquo;s source URL, saving both time and
storage space.</p>
<p>Caching of import models is switched on by default. To turn it off,
use the policy property <code>cacheModels</code>, or call the method
<code>setCacheModels( boolean caching )</code> with <code>caching = false</code>. The
document manager&rsquo;s current model cache can be cleared at any time
by calling <code>clearCache()</code>.</p>
<h2 id="the-generic-ontology-type-ontresource">The generic ontology type: OntResource</h2>
<p>All of the classes in the ontology API that represent ontology
values have
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/OntResource.html"><code>OntResource</code></a>
as a common super-class. This makes <code>OntResource</code> a good place to
put shared functionality for all such classes, and makes a handy
common return value for general methods. The Java interface
<code>OntResource</code> extends Jena&rsquo;s RDF
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/Resource.html"><code>Resource</code></a>
interface, so any general method that accepts a resource or an
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/RDFNode.html"><code>RDFNode</code></a>
will also accept an <code>OntResource</code>, and consequently, any other
ontology value.</p>
<p>Some of the common attributes of ontology resources that are
expressed through methods on OntResource are shown below:</p>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td>versionInfo</td>
<td>A string documenting the version or history of this resource</td>
</tr>
<tr>
<td>comment</td>
<td>A general comment associated with this value</td>
</tr>
<tr>
<td>label</td>
<td>A human-readable label</td>
</tr>
<tr>
<td>seeAlso</td>
<td>Another web location to consult for more information about this resource</td>
</tr>
<tr>
<td>isDefinedBy</td>
<td>A specialisation of seeAlso that is intended to supply a definition of this resource</td>
</tr>
<tr>
<td>sameAs</td>
<td>Denotes another resource that this resource is equivalent to</td>
</tr>
<tr>
<td>differentFrom</td>
<td>Denotes another resource that is distinct from this resource (by definition)</td>
</tr>
</tbody>
</table>
<p>For each of these properties, there is a standard pattern of
available methods:</p>
<table>
<thead>
<tr>
<th>Method</th>
<th>Effect</th>
</tr>
</thead>
<tbody>
<tr>
<td>add&lt;property&gt;</td>
<td>Add an additional value for the given property</td>
</tr>
<tr>
<td>set&lt;property&gt;</td>
<td>Remove any existing values for the property, then add the given value</td>
</tr>
<tr>
<td>list&lt;property&gt;</td>
<td>Return an iterator ranging over the values of the property</td>
</tr>
<tr>
<td>get&lt;property&gt;</td>
<td>Return the value for the given property, if the resource has one. If not, return null. If it has more than one value, an arbitrary selection is made.</td>
</tr>
<tr>
<td>has&lt;property&gt;</td>
<td>Return true if there is at least one value for the given property. Depending on the name of the property, this is sometimes is&lt;property&gt;</td>
</tr>
<tr>
<td>remove&lt;property&gt;</td>
<td>Removes a given value from the values of the property on this resource. Has no effect if the resource does not have that value.</td>
</tr>
</tbody>
</table>
<p>For example: <code>addSameAs( Resource r )</code>, or
<code>isSameAs( Resource r )</code>. For full details of the individual
methods, please consult the Javadoc.</p>
<p><code>OntResource</code> defines some other general utility methods. For
example, to find out how many values a resource has for a given
property, you can call <code>getCardinality( Property p )</code>. To delete
the resource from the ontology altogether, you can call <code>remove()</code>.
The effect of this is to remove every statement that mentions this
resource as a subject or object of a statement.</p>
<p>To get the value of a given property, use
<code>getPropertyValue( Property p )</code>. To set it,
<code>setPropertyValue( Property p, RDFNode value )</code>. Continuing the
naming pattern, the values of a named property can be listed (with
<code>listPropertyValues</code>), removed (with <code>removeProperty</code>) or added
(with <code>addProperty</code>).</p>
<p>Finally, <code>OntResource</code> provides methods for listing, getting and
setting the <code>rdf:type</code> of a resource, which denotes a class to
which the resource belongs (noting that, in RDF and OWL, a
resource can belong to many classes at once). The <code>rdf:type</code>
property is one for which many entailment rules are defined in the
semantic models of the various ontology languages. Therefore, the
values that <code>listRDFTypes()</code> returns is more than usually dependent
on the reasoner bound to the ontology model. For example,
suppose we have class <code>A</code>, class <code>B</code> which is a subclass of <code>A</code>, and
resource <code>x</code> whose asserted <code>rdf:type</code> is <code>B</code>. With no reasoner,
listing <code>x</code>'s RDF types will return only <code>B</code>. If the reasoner is able
to calculate the closure of the subclass hierarchy (and most can),
<code>x</code>'s RDF types would also include <code>A</code>. A complete OWL reasoner would
also infer that <code>x</code> has <code>rdf:type</code> <code>owl:Thing</code> and <code>rdf:Resource</code>.</p>
<p>For some tasks, getting a complete list of the RDF types of a
resource is exactly what is needed. For other tasks, this is not
the case. If you are developing an ontology editor, for example,
you may want to distinguish in its display between inferred and
asserted types. In the above example, only <code>x rdf:type B</code> is
asserted, everything else is inferred. One way to make this
distinction is to make use of the base model (see Figure 4).
Getting the resource from the base model and listing the type
properties there would return only the asserted values. For
example:</p>
<pre><code>// create the base model
String SOURCE = &quot;http://www.eswc2006.org/technologies/ontology&quot;;
String NS = SOURCE + &quot;#&quot;;
OntModel base = ModelFactory.createOntologyModel( OWL_MEM );
base.read( SOURCE, &quot;RDF/XML&quot; );
// create the reasoning model using the base
OntModel inf = ModelFactory.createOntologyModel( OWL_MEM_MICRO_RULE_INF, base );
// create a dummy paper for this example
OntClass paper = base.getOntClass( NS + &quot;Paper&quot; );
Individual p1 = base.createIndividual( NS + &quot;paper1&quot;, paper );
// list the asserted types
for (Iterator&lt;Resource&gt; i = p1.listRDFTypes(); i.hasNext(); ) {
System.out.println( p1.getURI() + &quot; is asserted in class &quot; + i.next() );
}
// list the inferred types
p1 = inf.getIndividual( NS + &quot;paper1&quot; );
for (Iterator&lt;Resource&gt; i = p1.listRDFTypes(); i.hasNext(); ) {
System.out.println( p1.getURI() + &quot; is inferred to be in class &quot; + i.next() );
}
</code></pre>
<p>For other user interface or presentation tasks, we may want
something between the complete list of types and the base list of
only the asserted values. Consider the class hierarchy in figure 5
(i):</p>
<p><img src="./direct-hierarchy.png" alt="Diagram showing direct relationships" title="asserted and direct relationships">
<br />Figure 5: asserted and inferred relationships</p>
<p>Figure 5 (i) shows a base model, containing a class hierarchy and
an instance <code>x</code>. Figure 5 (ii) shows the full set of relationships
that might be inferred from this base model. In Figure 5 (iii), we
see only the <em>direct</em> or maximally specific relationships. For
example, in 5 (iii) <code>x</code> does not have <code>rdf:type A</code>, since this is an
relationship that is covered by the fact that <code>x</code> has <code>rdf:type D</code>,
and <code>D</code> is a subclass of <code>A</code>. Notice also that the <code>rdf:type B</code> link is
also removed from the direct graph, for a similar reason. Thus the
direct graph hides relationships from both the inferred and
asserted graphs. When displaying instance <code>x</code> in a user interface, particularly
in a tree view of some kind, the direct graph is often the most
useful as it contains the useful information in the most compact
form.</p>
<p>To list the RDF types of a resource, use:</p>
<pre><code>listRDFTypes() // assumes not-direct
listRDFTypes( boolean direct ) // if direct=true, show only direct relationships
</code></pre>
<p>Related methods allow the <code>rdf:type</code> to be tested, set and
returned.</p>
<h2 id="ontology-classes-and-basic-class-expressions">Ontology classes and basic class expressions</h2>
<p>Classes are the basic building blocks of an ontology. A simple
class is represented in Jena by an
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/OntClass.html">OntClass</a>
object. As <a href="#rdf-polymorphism">mentioned above</a>, an ontology class
is a facet of an RDF resource. One way, therefore, to get an
ontology class is to convert a plain RDF resource into
its class facet. Assume that <code>m</code> is a
suitably defined <code>OntModel</code>, into which the ESWC ontology has
already been read, and that <code>NS</code> is a variable denoting the
ontology namespace:</p>
<pre><code>Resource r = m.getResource( NS + &quot;Paper&quot; );
OntClass paper = r.as( OntClass.class );
</code></pre>
<p>This can be shortened by calling <code>getOntClass()</code> on the ontology
model:</p>
<pre><code>OntClass paper = m.getOntClass( NS + &quot;Paper&quot; );
</code></pre>
<p>The <code>getOntClass</code> method will retrieve the resource with the given
URI, and attempt to obtain the <code>OntClass</code> facet. If either of these
operations fail, <code>getOntClass()</code> will return null. Compare this
with the <code>createClass</code> method, which will reuse an existing
resource if possible, or create a new class resource if not:</p>
<pre><code>OntClass paper = m.createClass( NS + &quot;Paper&quot; );
OntClass bestPaper = m.createClass( NS + &quot;BestPaper&quot; );
</code></pre>
<p>You can use the create class method to create an anonymous class –
a class description with no associated URI. Anonymous classes are
often used when building more complex ontologies in OWL.
They are less useful in RDFS.</p>
<pre><code>OntClass anonClass = m.createClass();
</code></pre>
<p>Once you have the ontology class object, you can begin processing
it through the methods defined on <code>OntClass</code>. The attributes of a
class are handled in a similar way to the attributes of
<code>OntResource</code>, above, with a collection of methods to set, add, get,
test, list and remove values. Properties of classes that are
handled in this way are:</p>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td>subClass</td>
<td>A subclass of this class, i.e. those classes that are declared <code>subClassOf</code> this class.</td>
</tr>
<tr>
<td>superClass</td>
<td>A super-class of this class, i.e. a class that this class is a <code>subClassOf</code>.</td>
</tr>
<tr>
<td>equivalentClass</td>
<td>A class that represents the same concept as this class. This is not just having the same class extension: the class &lsquo;British Prime Minister in 2003&rsquo; contains the same individual as the class &lsquo;the husband of Cherie Blair&rsquo;, but they represent different concepts.</td>
</tr>
<tr>
<td>disjointWith</td>
<td>Denotes a class with which this class has no instances in common.</td>
</tr>
</tbody>
</table>
<p>Thus, in our example ontology, we can print a list the subclasses
of an <code>Artefact</code> as follows:</p>
<pre><code>OntClass artefact = m.getOntClass( NS + &quot;Artefact&quot; );
for (Iterator&lt;OntClass&gt; i = artefact.listSubClasses(); i.hasNext(); ) {
OntClass c = i.next();
System.out.println( c.getURI() );
}
</code></pre>
<p>Note that, under RDFS and OWL semantics, each class is a sub-class
of itself (in other words, <code>rdfs:subClassOf</code> is reflexive). While
this is true in the semantics, Jena users have reported finding
it inconvenient. Therefore, the <code>listSubClasses</code> and
<code>listSuperClasses</code> convenience methods remove the reflexive from the list of
results returned by the iterator. However, if you use the plain
<code>Model</code> API to query for <code>rdfs:subClassOf</code> triples, assuming that a
reasoner is in use, the reflexive triple will appear among the deduced
triples.</p>
<p>Given an <code>OntClass</code> object, you can create or remove members of the
class extension – individuals that are instances of the class –
using the following methods:</p>
<table>
<thead>
<tr>
<th>Method</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td>listInstances()<br />listInstances(boolean direct)</td>
<td>Returns an iterator over those instances that include this class among their <code>rdf:type</code> values. The <code>direct</code> flag can be used to select individuals that are direct members of the class, rather than indirectly through the class hierarchy. Thus if <code>p1</code> has <code>rdf:type :Paper</code>, it will appear in the iterator returned by <code>listInstances</code> on <code>:Artefact</code>, but not in the iterator returned by <code>listInstances(false)</code> on <code>:Artefact</code>.</td>
</tr>
<tr>
<td>createIndividual()<br />createIndividual(String uri)</td>
<td>Adds a resource to the model, whose asserted <code>rdf:type</code> is this ontology class. If no URI is given, the individual is an anonymous resource.</td>
</tr>
<tr>
<td>dropIndividual(Resource individual)</td>
<td>Removes the association between the given individual and this ontology class. Effectively, this removes the <code>rdf:type</code> link between this class and the resource. Note that this is not the same as removing the individual altogether, unless the only thing that is known about the resource is that it is a member of the class. To delete an <code>OntResource</code>, including classes and individuals, use the <code>remove()</code> method.</td>
</tr>
</tbody>
</table>
<p>To test whether a class is a root of the class hierarchy in this
model (i.e. it has no known super-classes), call
<code>isHierarchyRoot()</code>.</p>
<p>The domain of a property is intended to allow entailments about the
class of an individual, given that it appears as a statement
subject. It is not a constraint that can be used to validate a
document, in the way that XML schema can do. Nevertheless, many
developers find it convenient to use the domain of a property to
document the design intent that the property only applies to known
instances of the domain class. Given this observation, it can be a
useful debugging or display aide to show the properties that have
this class among their domain classes. The method
<code>listDeclaredProperties()</code> attempts to identify the properties that
are intended to apply to instances of this class. Using
<code>listDeclaredProperties</code> is explained in detail in the
<a href="/documentation/notes/rdf-frames.html">RDF frames how-to</a>.</p>
<h2 id="ontology-properties">Ontology properties</h2>
<p>In an ontology, a <em>property</em> denotes the name of a relationship
between resources, or between a resource and a data value. It
corresponds to a predicate in logic representations. One
interesting aspect of RDFS and OWL is that
properties are not defined as aspects of some enclosing class, but
are first-class objects in their own right. This means that
ontologies and ontology-applications can store, retrieve and make
assertions about properties directly. Consequently, Jena has a set
of Java classes that allow you to conveniently manipulate the
properties represented in an ontology model.</p>
<p>A property in an ontology model is an extension of the core Jena
API class
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/Property.html"><code>Property</code></a>
and allows access to the additional information that can be
asserted about properties in an ontology language. The common API
super-class for representing ontology properties in Java is
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/OntProperty.html"><code>OntProperty</code></a>.
Again, using the pattern of add, set, get, list, has, and remove
methods, we can access the following attributes of an
<code>OntProperty</code>:</p>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td>subProperty</td>
<td>A sub property of this property; i.e. a property which is declared to be a <code>subPropertyOf</code> this property. If p is a sub property of q, and we know that <code>A p B</code> is true, we can infer that <code>A q B</code> is also true.</td>
</tr>
<tr>
<td>superProperty</td>
<td>A super property of this property, i.e. a property that this property is a <code>subPropertyOf</code></td>
</tr>
<tr>
<td>domain</td>
<td>Denotes the class or classes that form the domain of this property. Multiple domain values are interpreted as a conjunction. The domain denotes the class of value the property maps from.</td>
</tr>
<tr>
<td>range</td>
<td>Denotes the class or classes that form the range of this property. Multiple range values are interpreted as a conjunction. The range denotes the class of values the property maps to.</td>
</tr>
<tr>
<td>equivalentProperty</td>
<td>Denotes a property that is the same as this property.</td>
</tr>
<tr>
<td>inverse</td>
<td>Denotes a property that is the inverse of this property. Thus if q is the inverse of p, and we know that <code>A q B</code>, then we can infer that <code>B p A</code>.</td>
</tr>
</tbody>
</table>
<p>In the example ontology, the property <code>hasProgramme</code> has a domain
of <code>OrganizedEvent</code>, a range of <code>Programme</code> and the human-readable label &ldquo;has programme&rdquo;.
We can reconstruct this definition in an
empty ontology model as follows:</p>
<pre><code>OntModel m = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM );
OntClass programme = m.createClass( NS + &quot;Programme&quot; );
OntClass orgEvent = m.createClass( NS + &quot;OrganizedEvent&quot; );
ObjectProperty hasProgramme = m.createObjectProperty( NS + &quot;hasProgramme&quot; );
hasProgramme.addDomain( orgEvent );
body.addRange( programme );
body.addLabel( &quot;has programme&quot;, &quot;en&quot; );
</code></pre>
<p>As a further example, we can alternatively add information to an
existing ontology. To add a super-property <code>hasDeadline</code>, to
generalise the separate properties denoting the submission
deadline, notification deadline and camera-ready deadline, do:</p>
<pre><code>OntModel m = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM );
m.read( &quot;http://www.eswc2006.org/technologies/ontology&quot; );
DatatypeProperty subDeadline = m.getDatatypeProperty( NS + &quot;hasSubmissionDeadline&quot; );
DatatypeProperty notifyDeadline = m.getDatatypeProperty( NS + &quot;hasNotificationDeadline&quot; );
DatatypeProperty cameraDeadline = m.getDatatypeProperty( NS + &quot;hasCameraReadyDeadline&quot; );
DatatypeProperty deadline = m.createDatatypeProperty( NS + &quot;deadline&quot; );
deadline.addDomain( m.getOntClass( NS + &quot;Call&quot; ) );
deadline.addRange( XSD.dateTime );
deadline.addSubProperty( subDeadline );
deadline.addSubProperty( notifyDeadline );
deadline.addSubProperty( cameraDeadline );
</code></pre>
<p>Note that, although we called the <code>addSubProperty</code> method on the
object representing the new super-property, the serialized form of
the ontology will contain <code>rdfs:subPropertyOf</code> axioms on each of
the sub-property resources, since this is what the language
defines. Jena will, in general, try to allow symmetric access to
sub-properties and sub-classes from either direction.</p>
<h3 id="object-and-datatype-properties">Object and Datatype properties</h3>
<p>OWL refines the basic property type from RDF into two
sub-types: <em>object properties</em> and <em>datatype properties</em> (for more
details see
[<a href="http://www.w3.org/TR/owl-ref/#Property">OWL Reference</a>]). The
difference between them is that an object property can have only
individuals in its range, while a datatype property has concrete
data literals (only) in its range. Some OWL reasoners are able to
exploit the differences between object and datatype properties to
perform more efficient reasoning over ontologies. OWL also adds an
<em>annotation property</em>, which is defined to have no semantic
entailments, and so is useful when annotating ontology documents,
for example.</p>
<p>In Jena, the Java interfaces
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/ObjectProperty.html"><code>ObjectProperty</code></a>,
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/DatatypeProperty.html"><code>DatatypeProperty</code></a>
and
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/AnnotationProperty.html"><code>AnnotationProperty</code></a>
are sub-types of <code>OntProperty</code>. However, they do not have any
behaviours (methods) particular to themselves. Their existence
allows the more complex sub-types of ObjectProperty – transitive
properties and so forth – to be kept separate in the class
hierarchy. However, when you create an object property or datatype
property in a model, it will have the effect of asserting different
<code>rdf:type</code> statements into the underlying triple store.</p>
<h3 id="functional-properties">Functional properties</h3>
<p>OWL permits object and datatype properties to be <em>functional</em>
that is, for a given individual in the domain, the range value will
always be the same. In particular, if <code>father</code> is a functional
property, and individual <code>:jane</code> has <code>father :jim</code> and
<code>father :james</code>, a reasoner is entitled to conclude that <code>:jim</code> and
<code>:james</code> denote the same individual. A functional property is
equivalent to stating that the property has a maximum cardinality
of one.</p>
<p>Being a functional property is represented through the
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/FunctionalProperty.html"><code>FunctionalProperty</code></a>
facet of an ontology property object. If a property is declared
functional (test using the <code>isFunctional()</code> method), then the
method <code>asFunctionalProperty()</code> conveniently returns the functional property
facet. A non-functional property can be made functional through the
<code>convertToFunctionalProperty()</code> method. When you are creating a
property object, you also have the option of passing a Boolean
parameter to the <code>createObjectProperty()</code> method on <code>OntModel</code>.</p>
<h3 id="other-property-types">Other property types</h3>
<p>There are several additional sub-types of ObjectProperty that
represent additional capabilities of ontology properties. A
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/TransitiveProperty.html"><code>TransitiveProperty</code></a>
means that if p is transitive, and we know <code>:a p :b</code> and also
<code>b p :c</code>, we can infer that <code>:a p :c</code>. A
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/SymmetricProperty.html"><code>SymmetricProperty</code></a>
means that if p is symmetric, and we know <code>:a p :b</code>, we can infer
<code>:b p :a</code>. An
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/InverseFunctionalProperty.html"><code>InverseFunctionalProperty</code></a>
means that for any given range element, the domain value is unique.</p>
<p>Given that all properties are <code>RDFNode</code> objects, and therefore
support the <code>as()</code> method, you can use <code>as()</code> to change from an
object property facet to a transitive property facet. To make this
more straightforward, the <code>OntProperty</code> Java class has a number of
methods that support directly switching to the corresponding facet
view:</p>
<pre><code>public TransitiveProperty asTransitiveProperty();
public FunctionalProperty asFunctionalProperty();
public SymmetricProperty asSymmetricPropery();
public InverseFunctionalProperty asInverseFunctionalProperty();
</code></pre>
<p>These methods all assume that the underlying model will support
this change in perspective. If not, the operation will fail with a
<code>ConversionException</code>. For example, if a given property <code>p</code> is not
asserted to be a transitive property in the underlying RDF model, then invoking
<code>p.asTransitiveProperty()</code> will throw a conversion exception. The
following methods will, if necessary, add additional information
(i.e. the additional <code>rdf:type</code> statement) to allow the conversion
to an alternative facet to succeed.</p>
<pre><code>public TransitiveProperty convertToTransitiveProperty();
public FunctionalProperty convertToFunctionalProperty();
public SymmetricProperty convertToSymmetricPropery();
public InverseFunctionalProperty convertToInverseFunctionalProperty();
</code></pre>
<p>Sometimes it is convenient not to check whether the <code>.as()</code> conversion
is warranted by the underlying data. This may be the case, for example,
if the developer knows that the conversions are correct given the information from
an external ontology which is not currently loaded. To allow <code>.as()</code> to always
succeed, set the attribute <code>strictMode</code> to <code>false</code> on the <code>OntModel</code>
object: <code>myOntModel.setStrictMode( false )</code>.</p>
<p>Finally, methods beginning <code>is...</code> (e.g. <code>isTransitiveProperty</code>)
allow you to test whether a given property would support a given
sub-type facet.</p>
<h2 id="more-complex-class-expressions">More complex class expressions</h2>
<p>We introduced the handling of basic, named classes above. These are
the only kind of class descriptions available in RDFS. In OWL,
however, there are a number of additional types of class
expression, which allow richer and more expressive descriptions of
concepts. There are two main categories of additional class
expression: <em>restrictions</em> and <em>Boolean expressions</em>. We&rsquo;ll examine
each in turn.</p>
<h3 id="restriction-class-expressions">Restriction class expressions</h3>
<p>A
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/Restriction.html">restriction</a>
defines a class by reference to one of the properties of the
individuals that comprise the members of the class, and then
placing some constraint on that property. For example, in a simple
view of animal taxonomy, we might say that mammals are covered in
fur, and birds in feathers. Thus the property <code>hasCovering</code> is in
one case restricted to have the value <code>fur</code>, in the other to have
the value <code>feathers</code>. This is a <em>has value restriction</em>. Six
restriction types are currently defined by OWL:</p>
<table>
<thead>
<tr>
<th>Restriction type</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td>has value</td>
<td>The restricted property has exactly the given value.</td>
</tr>
<tr>
<td>all values from</td>
<td>All values of the restricted property, if it has any, are members of the given class.</td>
</tr>
<tr>
<td>some values from</td>
<td>The property has at least one value which is a member of the given class.</td>
</tr>
<tr>
<td>cardinality</td>
<td>The property has exactly <em>n</em> values, for some positive integer n.</td>
</tr>
<tr>
<td>min cardinality</td>
<td>The property has at least <em>n</em> values, for some positive integer n.</td>
</tr>
<tr>
<td>max cardinality</td>
<td>The property has at most <em>n</em> values, for some positive integer n.</td>
</tr>
</tbody>
</table>
<p>Note that, at present, the Jena
ontology API has only limited support for OWL2&rsquo;s qualified
cardinality restrictions (i.e. <code>cardinalityQ</code>, <code>minCardinalityQ</code>
and <code>maxCardinalityQ</code>). Qualified cardinality restrictions are
encapsulated in the interfaces <code>CardinalityQRestriction</code>,
<code>MinCardinalityQRestriction</code> and <code>CardinalityQRestriction</code>.
<code>OntModel</code> also provides methods for creating and accessing
qualified cardinality restrictions. Since they are not part of the
OWL 1.0 language definition, qualified cardinality restrictions are
not supported in OWL ontologies. Qualified cardinality restrictions
were added to the OWL 2 update. OWL2 support in Jena will be
added in due course.</p>
<p>Jena provides a number of ways of creating restrictions, or
retrieving them from a model. Firstly, you can retrieve a general
restriction from the model by its URI, if known.</p>
<pre><code>// get restriction with a given URI
Restriction r = m.getRestriction( NS + &quot;theName&quot; );
</code></pre>
<p>You can create a new restriction created by nominating the property
that the restriction applies to:</p>
<pre><code>// anonymous restriction on property p
OntProperty p = m.createOntProperty( NS + &quot;p&quot; );
Restriction anonR = m.createRestriction( p );
</code></pre>
<p>Since a restriction is typically not assigned a URI in an ontology,
retrieving an existing restriction by name may not be possible.
However, you can list all of the restrictions in a model and search
for the one you want:</p>
<pre><code>Iterator&lt;Restriction&gt; i = m.listRestrictions();
while (i.hasNext()) {
Restriction r = i.next();
if (isTheOne( r )) {
// handle the restriction
}
}
</code></pre>
<p>A common case is that we want the restrictions on some property
<code>p</code>. In this case, from an object denoting <code>p</code> we can list the
restrictions that mention that property:</p>
<pre><code>OntProperty p = m.getProperty( NS + &quot;p&quot; );
Iterator&lt;Restriction&gt; i = p.listReferringRestrictions();
while (i.hasNext()) {
Restriction r = i.next();
// now handle the restriction ...
}
</code></pre>
<p>A general restriction can be converted to a specific type of
restriction via <code>as...</code> methods (if the information is already in the
model), or, if the information is not in the model, via
<code>convertTo...</code> methods. For example, to convert the example
restriction <code>r</code> from the example above to an all values from
restriction, we can do the following:</p>
<pre><code>OntClass c = m.createClass( NS + &quot;SomeClass&quot; );
AllValuesFromRestriction avf = r.convertToAllValuesFromRestriction( c );
</code></pre>
<p>To create a particular restriction <em>ab initio</em>, we can use the
creation methods defined on <code>OntModel</code>. For example:</p>
<pre><code>OntClass c = m.createClass( NS + &quot;SomeClass&quot; );
ObjectProperty p = m.createObjectProperty( NS + &quot;p&quot; );
// null denotes the URI in an anonymous restriction
AllValuesFromRestriction avf = m.createAllValuesFromRestriction( null, p, c );
</code></pre>
<p>Assuming that the above code fragment was using a model <code>m</code> which
was created with the OWL language profile, it creates a instance of
an OWL restriction that would have the following definition in
RDF/XML:</p>
<pre><code>&lt;owl:Restriction&gt;
&lt;owl:onProperty rdf:resource=&quot;#p&quot;/&gt;
&lt;owl:allValuesFrom rdf:resource=&quot;#SomeClass&quot;/&gt;
&lt;/owl:Restriction&gt;
</code></pre>
<p>Once we have a particular restriction object, there are methods
following the standard add, get, set and test naming pattern to
access the aspects of the restriction. For example, in a camera
ontology, we might find this definition of a class describing
Large-Format cameras:</p>
<pre><code>&lt;owl:Class rdf:ID=&quot;Large-Format&quot;&gt;
&lt;rdfs:subClassOf rdf:resource=&quot;#Camera&quot;/&gt;
&lt;rdfs:subClassOf&gt;
&lt;owl:Restriction&gt;
&lt;owl:onProperty rdf:resource=&quot;#body&quot;/&gt;
&lt;owl:allValuesFrom rdf:resource=&quot;#BodyWithNonAdjustableShutterSpeed&quot;/&gt;
&lt;/owl:Restriction&gt;
&lt;/rdfs:subClassOf&gt;
&lt;/owl:Class&gt;
</code></pre>
<p>Here&rsquo;s one way to access the components of the all values from
restriction. Assume <code>m</code> contains a suitable camera ontology:</p>
<pre><code>OntClass largeFormat = m.getOntClass( camNS + &quot;Large-Format&quot; );
for (Iterator&lt;OntClass&gt; i = LargeFormat.listSuperClasses( true ); i.hasNext(); ) {
OntClass c = i.next();
if (c.isRestriction()) {
Restriction r = c.asRestriction();
if (r.isAllValuesFromRestriction()) {
AllValuesFromRestriction av = r.asAllValuesFromRestriction();
System.out.println( &quot;AllValuesFrom class &quot; +
av.getAllValuesFrom().getURI() +
&quot; on property &quot; + av.getOnProperty().getURI() );
}
}
}
</code></pre>
<h3 id="boolean-class-expressions">Boolean class expressions</h3>
<p>Most developers are familiar with the use of Boolean operators to
construct propositional expressions: conjunction (and), disjunction
(or) and negation (not). OWL provides a means for constructing
expressions describing classes with analogous operators, by
considering class descriptions in terms of the set of individuals
that comprise the members of the class.</p>
<p>Suppose we wish to say that an instance <code>x</code> has <code>rdf:type</code> <code>A</code> <strong>and</strong>
<code>rdf:type</code> <code>B</code>. This means that <code>x</code> is both a member of the set of
individuals in <code>A</code>, and in the set of individuals in <code>B</code>. Thus, <code>x</code> lies
in the <em>intersection</em> of classes <code>A</code> and <code>B</code>. If, on the other hand, <code>A</code>
is either has <code>rdf:type</code> <code>A</code> <strong>or</strong> <code>B</code>, then <code>x</code> must lie in the <em>union</em>
of <code>A</code> and <code>B</code>. Finally, to say that x does <strong>not</strong> have <code>rdf:type</code> <code>A</code>,
it must lie in the <em>complement</em> of <code>A</code>. These operations, union,
intersection and complement are the Boolean operators for
constructing class expressions. While complement takes only a
single argument, union and intersection must necessarily take more
than one argument. Before continuing with constructing and using
Boolean class expressions, let&rsquo;s briefly to discuss lists.</p>
<h3 id="list-expressions">List expressions</h3>
<p>RDF originally had three container types: <code>Seq</code>, <code>Alt</code> and <code>Bag</code>.
While useful, these are all open forms: it is not possible to say
that a given container has a fixed number of values.
Lists have subsequently been added to the
core RDF specification, and are used extensively in OWL. A list
follows the well-known <em>cons cell</em> pattern from Lisp, Prolog and
other list-handling languages. Each cell of a list is either the
end-of-list terminator (<code>nil</code> in Lisp), or is a pair consisting of
a value and a pointer to the cell that is the first cell on the
tail of the list. In RDF lists, the end-of-list is marked by a
resource with name <code>rdf:nil</code>, while each list cell is an anonymous
resource with two properties, one denoting the tail and the other
the value. Fortunately, this complexity is hidden by some simple
syntax:</p>
<pre><code>&lt;p rdf:parseType=&quot;collection&quot;&gt;
&lt;A /&gt;
&lt;B /&gt;
&lt;/p&gt;
</code></pre>
<p>According to the RDF specification, this list of two elements has
the following expansion as RDF triples:</p>
<pre><code>&lt;p&gt;
&lt;rdf:first&gt;&lt;A /&gt;&lt;/rdf:first&gt;
&lt;rdf:rest&gt;
&lt;rdf:first&gt;&lt;B /&gt;&lt;/rdf:first&gt;
&lt;rdf:rest rdf:resource=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#nil&quot;/&gt;
&lt;/rdf:rest&gt;
&lt;/p&gt;
</code></pre>
<p>Given this construction, a well formed list (one with exactly one
<code>rdf:first</code> and <code>rdf:rest</code> per cons cell) has a precisely
determined set of members. Incidentally, the same list in Turtle
is even more compact:</p>
<pre><code>:example
:p ( :A :B ).
</code></pre>
<p>Although lists are defined in the generic RDF model in Jena, they
are extensively used by the ontology API so we mention them here.
Full details of the methods defined are in the
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/RDFList.html"><code>RDFList</code> javadoc</a>.</p>
<p>Various means of constructing lists are defined in
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/Model.html"><code>Model</code></a>, as
variants on <code>createList</code>. For example, we can construct a list of
three classes as follows:</p>
<pre><code>OntModel m = ModelFactory.createOntModel();
OntClass c0 = m.createClass( NS + &quot;c0&quot; );
OntClass c1 = m.createClass( NS + &quot;c1&quot; );
OntClass c2 = m.createClass( NS + &quot;c2&quot; );
RDFList cs = m.createList( new RDFNode[] {c0, c1, c2} );
</code></pre>
<p>Alternatively, we can build a list one element at time:</p>
<pre><code>OntModel m = ModelFactory.createOntModel();
RDFList cs = m.createList(); // Cs is empty
cs = cs.cons( m.createClass( NS + &quot;c0&quot; ) );
cs = cs.cons( m.createClass( NS + &quot;c1&quot; ) );
cs = cs.cons( m.createClass( NS + &quot;c2&quot; ) );
</code></pre>
<p>Note that these two approaches end with the classes in the lists in
opposite orders, since the <code>cons</code> operation adds a new list cell to
the front of the list. Thus the second list will run <code>c2</code> to <code>c0</code>. In
the ontology operations we are discussing here, the order of values
in the list is not considered significant.</p>
<p>Finally, a resource which is a cell in a list sequence will accept
<code>.as( RDFList.class )</code></p>
<p>Once the list has been created or obtained from the model,
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/RDFList.html"><code>RDFList</code></a>
methods may be used to access members of the list, iterate over the
list, and so forth. For example:</p>
<pre><code>System.out.println( &quot;List has &quot; + myRDFList.size() + &quot; members:&quot; );
for (Iterator&lt;RDFNode&gt; i = myRDFList.iterator(); i.hasNext(); ) {
System.out.println( i.next() );
}
</code></pre>
<h3 id="intersection-union-and-complement-class-expressions">Intersection, union and complement class expressions</h3>
<p>Given Jena&rsquo;s ability to construct lists, building intersection and
union class expressions is straightforward. The <code>create</code> methods on
OntModel allow us to construct an intersection or union directly.
Alternatively, given an existing OntClass, we can use the
<code>convertTo...</code> methods to construct facet representing the more
specialised expressions. For example, we can define the class of UK
industry-related conferences as the intersection of conferences
with a UK location and conferences with an industrial track. Here&rsquo;s
the XML declaration:</p>
<pre><code>&lt;owl:Class rdf:ID=&quot;UKIndustrialConference&quot;&gt;
&lt;owl:intersectionOf rdf:parseType=&quot;Collection&quot;&gt;
&lt;owl:Restriction&gt;
&lt;owl:onProperty rdf:resource=&quot;#hasLocation&quot;/&gt;
&lt;owl:hasValue rdf:resource=&quot;#united_kingdom&quot;/&gt;
&lt;/owl:Restriction&gt;
&lt;owl:Restriction&gt;
&lt;owl:onProperty rdf:resource=&quot;#hasPart&quot;/&gt;
&lt;owl:someValuesFrom rdf:resource=&quot;#IndustryTrack&quot;/&gt;
&lt;/owl:Restriction&gt;
&lt;/owl:intersectionOf&gt;
&lt;/owl:Class&gt;
</code></pre>
<p>Or, more compactly in N3/Turtle:</p>
<pre><code>:UKIndustrialConference a owl:Class ;
owl:intersectionOf (
[a owl:Restriction ;
owl:onProperty :hasLocation ;
owl:hasValue :united_kingdom]
[a owl:Restriction ;
owl:onProperty :hasPart ;
owl:someValuesFrom :IndustryTrack]
)
</code></pre>
<p>Here is code to create this class declaration using Jena, assuming
that <code>m</code> is a model into which the ESWC ontology has been read:</p>
<pre><code>// get the class references
OntClass place = m.getOntClass( NS + &quot;Place&quot; );
OntClass indTrack = m.getOntClass( NS + &quot;IndustryTrack&quot; );
// get the property references
ObjectProperty hasPart = m.getObjectProperty( NS + &quot;hasPart&quot; );
ObjectProperty hasLoc = m.getObjectProperty( NS + &quot;hasLocation&quot; );
// create the UK instance
Individual uk = place.createIndividual( NS + &quot;united_kingdom&quot; );
// now the anonymous restrictions
HasValueRestriction ukLocation =
m.createHasValueRestriction( null, hasLoc, uk );
SomeValuesFromRestriction hasIndTrack =
m.createHasValueRestriction( null, hasPart, indTrack );
// finally create the intersection class
IntersectionClass ukIndustrialConf =
m.createIntersectionClass( NS + &quot;UKIndustrialConference&quot;,
m.createList( new RDFNode[] {ukLocation, hasIndTrack} ) );
</code></pre>
<p>Union and intersection class expressions are very similar, so
Jena defines a common super-class
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/BooleanClassDescription.html"><code>BooleanClassDescription</code></a>.
This class provides access to the <em>operands</em> to the expression. In
the intersection example above, the operands are the two restrictions. The
<code>BooleanClassDescription</code> class allows us to set the operands
<em>en masse</em> by supplying a list, or to be added or deleted one at a
time.</p>
<p>Complement class expressions are very similar. The principal
difference is that they take only a single class as operand, and
therefore do not accept a list of operands.</p>
<h3 id="enumerated-classes">Enumerated classes</h3>
<p>The final type class expression allows by OWL is the enumerated
class. Recall that a class is a set of individuals. Often, we want
to define the members of the class <em>implicitly</em>: for example, &ldquo;the class
of UK conferences&rdquo;. Sometimes it is convenient to define a class
<em>explicitly</em>, by stating the individuals the class contains. An
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/EnumeratedClass.html">enumerated class</a>
is exactly the class whose members are the given individuals. For
example, we know that the class of PrimaryColours contains exactly
red, green and blue, and no others.</p>
<p>In Jena, an enumerated class is created in a similar way to other
classes. The set of values that comprise the enumeration is
described by an RDFList. For example, here&rsquo;s a class defining the
countries that comprise the United Kingdom:</p>
<pre><code>&lt;owl:Class rdf:ID=&quot;UKCountries&quot;&gt;
&lt;owl:oneOf rdf:parseType=&quot;Collection&quot;&gt;
&lt;eswc:Place rdf:about=&quot;#england&quot;/&gt;
&lt;eswc:Place rdf:about=&quot;#scotland&quot;/&gt;
&lt;eswc:Place rdf:about=&quot;#wales&quot;/&gt;
&lt;eswc:Place rdf:about=&quot;#northern_ireland&quot;/&gt;
&lt;/owl:oneOf&gt;
&lt;/owl:Class&gt;
</code></pre>
<p>To list the contents of this enumeration, we could do the
following:</p>
<pre><code>OntClass place = m.getOntClass( NS + &quot;Place&quot; );
EnumeratedClass ukCountries =
m.createEnumeratedClass( NS + &quot;UKCountries&quot;, null );
ukCountries.addOneOf( place.createIndividual( NS + &quot;england&quot; ) );
ukCountries.addOneOf( place.createIndividual( NS + &quot;scotland&quot; ) );
ukCountries.addOneOf( place.createIndividual( NS + &quot;wales&quot; ) );
ukCountries.addOneOf( place.createIndividual( NS + &quot;northern_ireland&quot; ) );
for (Iterator i = UKCountries.listOneOf(); i.hasNext(); ) {
Resource r = (Resource) i.next();
System.out.println( r.getURI() );
}
</code></pre>
<p>An OWL <code>DataRange</code> is similar to an enumerated class, except that the members
of the <code>DataRange</code> are literal values, such as integers, dates or strings. See the
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/DataRange.html"><code>DataRange</code> javadoc</a>
for more details.</p>
<h3 id="listing-classes">Listing classes</h3>
<p>In many applications, we need to inspect the set of classes
in an ontology. The <code>list...</code> methods on <code>OntModel</code> provide a variety
of means of listing types of class. The methods available include:</p>
<pre><code>public ExtendedIterator&lt;OntClass&gt; listClasses();
public ExtendedIterator&lt;EnumeratedClass&gt; listEnumeratedClasses();
public ExtendedIterator&lt;UnionClass&gt; listUnionClasses();
public ExtendedIterator&lt;ComplementClass&gt; listComplementClasses();
public ExtendedIterator&lt;IntersectionClass&gt; listIntersectionClasses();
public ExtendedIterator&lt;Restriction&gt; listRestrictions();
public ExtendedIterator&lt;OntClass&gt; listNamedClasses();
public ExtendedIterator&lt;OntClass&gt; listHierarchyRootClasses();
</code></pre>
<p>The last two methods deserve special mention. In OWL, class
expressions are typically not named, but are denoted by anonymous
resources (aka <em>bNodes</em>). In many applications, such as displaying
an ontology in a user interface, we want to pick out the named
classes only, ignoring those denoted by bNodes. This is what
<code>listNamedClasses()</code> does. The method <code>listHierarchyRootClasses()</code>
identifies the classes that are uppermost in the class hierarchy
contained in the given model. These are the classes that have no
super-classes. The iteration returned by
<code>listHierarchyRootClasses()</code> <strong>may</strong> contain anonymous classes. To
get a list of named hierarchy root classes, i.e. the named classes
that lie closest to the top of the hierarchy (alternatively: the
shallowest fringe of the hierarchy consisting solely of named
classes), use the
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/OntTools.html">OntTools</a>
method <code>namedHierarchyRoots()</code>.</p>
<p>You should also note that it is important to close the iterators
returned from the <code>list...</code> methods, particularly when the underlying
store is a database. This is necessary so that any state (e.g. the
database connection resources) can be released. Closing happens
automatically when the <code>hasNext()</code> method on the iterator returns
<code>false</code>. If your code does not iterate all the way to the end of the
iterator, you should call the <code>close()</code> method explicitly. Note
also that the values returned by these iterators will depend on the
asserted data and the reasoner being used. For example, if the
model contains a <code>Restriction</code>, that restriction will only be
returned by the listClasses() iterator if the model is bound to a
reasoner that can infer that any restriction is also be a class,
since <code>Restriction</code> is a subClassOf <code>Class</code>. This difference can be
exploited by the programmer: to list classes and restrictions
separately, perform the <code>listClasses()</code> and <code>listRestrictions()</code>
methods on the base model only, or on a model with no reasoner
attached.</p>
<h2 id="instances-or-individuals">Instances or individuals</h2>
<p>In OWL Full any value can be an individual – and
thus the subject of triples in the RDF graph other than ontology
declarations. In OWL Lite and DL, the language terms and the
instance data that the application is working with are kept
separate, by definition of the language. Jena therefore supports a
simple notion of an
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/Individual.html"><code>Individual</code></a>,
which is essentially an alias for <code>Resource</code>. While <code>Individual</code>s
are largely synonymous with <code>Resource</code>s, they do provide an
programming interface that is consistent with the other Java
classes in the ontology API.</p>
<p>There are two ways to create individuals. Both requires the class
to which the individual will initially belong:</p>
<pre><code>OntClass c = m.createClass( NS + &quot;SomeClass&quot; );
// first way: use a call on OntModel
Individual ind0 = m.createIndividual( NS + &quot;ind0&quot;, c );
// second way: use a call on OntClass
Individual ind1 = c.createIndividual( NS + &quot;ind1&quot; );
</code></pre>
<p>The only real difference between these approaches is that the
second way will create the individual in the same model that the
class is attached to (see the <code>getModel()</code> method). In both of the
above examples the individual is named, but this is not necessary.
The method <code>OntModel.createIndividual( Resource cls )</code> creates an
anonymous individual belonging to the given class. Note that the
type of the class parameter is only <code>Resource</code>. You are not
required to use <code>as()</code> to present a <code>Resource</code> to an <code>OntClass</code>
before calling this method, though of course an <code>OntClass</code> is a
<code>Resource</code> so using an <code>OntClass</code> will work perfectly well.</p>
<p><code>Individual</code> provides a set of methods for testing and manipulating
the ontology classes to which an individual belongs. This is a
convenience: OWL and RDFS denote class membership through the
<code>rdf:type</code> property, and methods for manipulating and testing
<code>rdf:type</code> are defined on <code>OntResource</code>. You may use either
approach interchangeably.</p>
<h2 id="ontology-meta-data">Ontology meta-data</h2>
<p>In OWL, but not RDFS, meta-data about the ontology
itself is encoded as properties on an individual of class
<code>owl:Ontology</code>. By convention,
the URI of this individual is the URL, or web address, of the ontology document
itself. In the XML serialisation, this is typically shown as:</p>
<pre><code>&lt;owl:Ontology rdf:about=&quot;&quot;&gt;
&lt;/owl:Ontology&gt;
</code></pre>
<p>Note that the construct <code>rdf:about=&quot;&quot;</code> does <em>not</em> indicate a
resource with no URI; it is in fact a shorthand way of referencing
the <em>base URI</em> of the document containing the ontology. The base
URI may be stated in the document through an <code>xml:base</code> declaration
in the XML preamble. The base URI can also be specified when
reading the document via Jena&rsquo;s Model API (see the <code>read()</code> methods
on <a href="/documentation/javadoc/jena/org/apache/jena/ontology/OntModel.html"><code>OntModel</code></a>
for reference).</p>
<p>We can attach various meta-data statements to this object to
indicate attributes of the ontology as a whole. The Java object
<code>Ontology</code> represents this special instance, and uses the standard
add, set, get, list, test and delete pattern to provide access to
the following attributes:</p>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td>backwardCompatibleWith</td>
<td>Names a prior version of this ontology that this version is compatible with.</td>
</tr>
<tr>
<td>incompatibleWith</td>
<td>Names a prior version of this ontology that this version is not compatible with</td>
</tr>
<tr>
<td>priorVersion</td>
<td>Names a prior version of this ontology.</td>
</tr>
<tr>
<td>imports</td>
<td>Names an ontology whose definitions this ontology includes</td>
</tr>
</tbody>
</table>
<p>In addition to these attributes, the Ontology element typically
contains common meta-data properties, such as comment, label and
version information.</p>
<p>In the Jena API, the ontology&rsquo;s metadata properties can be accessed
through the
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/Ontology.html"><code>Ontology</code></a>
interface. Suppose we wish to know the list of URI&rsquo;s that the
ontology imports. First we must obtain the resource representing the
ontology itself:</p>
<pre><code>String base = ...; // the base URI of the ontology
OntModel m = ...; // the model containing the ontology statements
Ontology ont = m.getOntology( base );
// now list the ontology imports
for (String imp : ont.listImportedOntologyURIs()) {
System.out.println( &quot;Ontology &quot; + base + &quot; imports &quot; + imp );
}
</code></pre>
<p>If the base URI of the ontology is not known, you can list all
resources of <code>rdf:type</code> <code>Ontology</code> in a given model by
<code>OntModel.listOntologies()</code>. If there is only one of these, it
should be safe to assume that it is <em>the</em> Ontology resource for the
ontology. However, you should note that if more than one ontology
document has been read in to the model (for example by including
the imports of a document), there may well be more than one
<code>Ontology</code> resource in the model. In this case, you may find it
useful to list the ontology resources in just the base model:</p>
<pre><code>OntModel m = ... // the model, including imports
OntModel mBase = ModelFactory.createOntologyModel(
OntModelSpec.OWL_MEM, m.getBaseModel() );
for (Iterator i = mBase.listOntologies(); i.hasNext(); ) {
Ontology ont = (Ontology) i.next();
// m's base model has ont as an import ...
}
</code></pre>
<p>A common practice is also to use the Ontology element to attach
<a href="http://dublincore.org/">Dublin Core metadata</a>
to the ontology document. Jena provides a copy
of the Dublin Core vocabulary, in <code>org.apache.jena.vocabulary.DCTerms</code>.
To attach a statement saying that the ontology was authored by John
Smith, we can say:</p>
<pre><code>Ontology ont = m.getOntology( baseURI );
ont.addProperty( DCTerms.creator, &quot;John Smith&quot; );
</code></pre>
<p>It is also possible to programmatically add imports and other
meta-data to a model, for example:</p>
<pre><code>String base = ...; // the base URI of the ontology
OntModel m = ...;
Ontology ont = m.createOntology( base );
ont.addImport( m.createResource( &quot;http://example.com/import1&quot; ) );
ont.addImport( m.createResource( &quot;http://example.com/import2&quot; ) );
</code></pre>
<p>Note that under default conditions, simply adding (or removing) an
<code>owl:imports</code> statement to a model will not cause the corresponding
document to be imported (or removed). However, by calling
<code>OntModel.setDynamicImports(true)</code>, the model will start noticing
the addition or removal of <code>owl:imports</code> statements.</p>
<h2 id="ontology-inference-overview">Ontology inference: overview</h2>
<p>You have the choice of whether to use the Ontology API with Jena&rsquo;s
reasoning capability turned on, and, if so, which of the various
reasoners to use. Sometimes a reasoner will add information to the
ontology model that it is not useful for your application to see. A
good example is an ontology editor. Here, you may wish to present
your users with the information they have entered in to their
ontology; the addition of the entailed information into the
editor&rsquo;s display would be very confusing. Since Jena does not have
a means for distinguishing inferred statements from those
statements asserted into the base model, a common choice for
ontology editors and similar applications is to run with no
reasoner.</p>
<p>In many other cases, however, it is the addition of the reasoner
that makes the ontology useful. For example, if we know that John
is the father of Mary, we would expect a &lsquo;yes&rsquo; if we query whether
John is the parent of Mary. The parent relationship is not
asserted, but we know from our ontology that <code>fatherOf</code> is a
sub-property of <code>parentOf</code>. If &lsquo;John fatherOf Mary&rsquo; is true, then
&lsquo;John parentOf Mary&rsquo; is also true. The integrated reasoning
capability in Jena exists to allow just such entailments to be seen
and used.</p>
<p>For a complete and thorough description of Jena&rsquo;s inference
capabilities, please see the
<a href="/documentation/inference/">reasoner documentation</a>. This section of
of the ontology API documentation is intended to serve as only a
brief guide and overview.</p>
<p>Recall from the introduction that the reasoners in Jena operate by
making it appear that triples <em>entailed</em> by the inference engine
are part of the model in just the same way as the asserted triples
(see Figure 2). The underlying architecture allows the reasoner to
be part of the same Java virtual machine (as is the case with the
built-in rule-based reasoners), or in a separate process on the
local computer, or even a remote computer. Of course, each of these
choices will have different characteristics of what reasoning
capabilities are supported, and what the implications for
performance are.</p>
<p>The reasoner attached to an ontology model, if any, is specified
through the
<a href="/documentation/javadoc/jena/org/apache/jena/ontology/OntModelSpec.html"><code>OntModelSpec</code></a>.
The methods <code>setReasoner()</code> and <code>setReasonerFactory()</code> on the model
spec are used to specify a reasoner. The setReasoner variant is
intended for use on a specification which will only be used to
build a single model. The factory variant is used where the
<code>OntModelSpec</code> will be used to build more than one model, ensuring
that each model gets its own reasoner object. The
<code>ReasonerRegistry</code> provides a collection of pre-built reasoners –
see the reasoner documentation for more details. However, it is
also possible for you to define your own reasoner that conforms to
the appropriate interface. For example, there is an in-process
interface to the open-source
<a href="https://github.com/stardog-union/pellet">Pellet reasoner</a>.</p>
<p>To facilitate the choice of reasoners for a given model, some
common choices have been included in the pre-built ontology model
specifications available as static fields on <code>OntModelSpec</code>. The
available choices are described in the section on
<a href="#ont-model-specs">ont model specifications</a>, above.</p>
<p>Depending on which of these choices is made, the statements
returned from queries to a given ontology model may vary
considerably.</p>
<h3 id="additional-notes">Additional notes</h3>
<p>Jena&rsquo;s inference machinery defines some specialised services that
are not exposed through the addition of extra triples to the model.
These are exposed by the
<a href="/documentation/javadoc/jena/org/apache/jena/rdf/model/InfModel.html"><code>InfModel</code></a>
interface; for convenience OntModel extends this interface to make
these services directly available to the user. Please note that
calling inference-specific methods on an ontology model that does
not contain a reasoner will have unpredictable results. Typically
these methods will have no effect or return null, but you should
not rely on this behaviour.</p>
<p>In general, inference models will add many additional
statements to a given model, including the axioms appropriate to
the ontology language. This is typically not something you will
want in the output when the model is serialized, so
<em><code>write()</code> on an ontology model <strong>will only write the statements from the base model</strong>.</em>
This is typically the desired behaviour, but there are occasions
(e.g. during debugging) when you may want to write the entire
model, virtual triples included. The easiest way to achieve this is
to call the <code>writeAll()</code> method on <code>OntModel</code>. An alternative
technique, which can sometimes be useful for a variety of
use-cases, including debugging, is to snapshot the model by
constructing a temporary plain model and adding to it: the contents
of the ontology model:</p>
<pre><code>OntModel m = ...
// snapshot the contents of ont model om
Model snapshot = ModelFactory.createDefaultModel();
snapshot.add( om );
</code></pre>
<h2 id="working-with-persistent-ontologies">Working with persistent ontologies</h2>
<p>A common way to work with ontology data is to load the ontology
axioms and instances at run-time from a set of source documents.
This is a very flexible approach, but has limitations. In
particular, your application must parse the source documents each
time it is run. For large ontologies, this can be a source of
significant overhead. Jena provides an implementation of the RDF
model interface that stores the triples persistently in a database.
This saves the overhead of loading the model each time, and means
that you can store RDF models significantly larger than the
computer&rsquo;s main memory, but at the expense of a higher overhead (a
database interaction) to retrieve and update RDF data from the
model. In this section we briefly discuss using the ontology API with
Jena&rsquo;s persistent database models.</p>
<p>For information on setting-up and accessing the persistent models
themselves, see the <a href="/documentation/tdb/index.html">TDB</a>
reference sections.</p>
<p>There are two somewhat separate requirements for persistently
storing ontology data. The first is making the main or base model
itself persistent. The second is re-using or creating persistent
models for the imports of an ontology. These two requirements are
handled slightly differently.</p>
<p>To retrieve a Jena model from the database API, we have to know its
name. Fortunately, common practice for ontologies on the Semantic
Web is that each is named with a URI. We use this URI to name the
model that is stored in the database. Note carefully what is
actually happening here: we are exploiting a feature of the
database sub-system to make persistently stored ontologies easy to
retrieve, but we are not in any sense resolving the URI of the
model. Once placed into the database, the name of the model is
treated as an opaque string.</p>
<p>To create a persistent model for the ontology
<code>http://example.org/Customers</code>, we create a model maker that will
access our underlying database, and use the ontology URI as the
database name. We then take the resulting persistent model, and use
it as the base model when constructing an ontology model:</p>
<pre><code>Model base = getMaker().createModel( &quot;http://example.org/Customers&quot; );
OntModel m = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM_RULE_INF, base );
</code></pre>
<p>Here we assume that the <code>getMaker()</code> method returns a suitably
initialized <code>ModelMaker</code> that will open the connection to the
database. This step only creates a persistent model named with the
ontology URI. To initialise the content, we must either add
statements to the model using the OntModel API, or do a one-time
read from a document:</p>
<pre><code>m.read( &quot;http://example.org/Customers&quot; );
</code></pre>
<p>Once this step is completed, the model contents may be accessed in
future without needing to read again.</p>
<p>If the Customers ontology imports other ontologies, using
<code>owl:imports</code>, the Jena Ontology API will build a
union model containing the closure of the imports. Even if the base
model is persistent, the predefined <code>OntModelSpec</code> objects only
specify memory models to contain the imported ontologies, since
memory models do not require any additional parameters.</p>
<p>To specify that the imported models should stored in, and retrieved
from, the database, we must update the ontology spec object to use
the model maker that encapsulates the database connection:</p>
<pre><code>OntModelSpec spec = new OntModelSpec( OntModelSpec.OWL_MEM_RULE_INF );
// set the model maker for the base model
spec.setBaseModelMaker( getMaker() );
// set the model maker for imports
spec.setImportModelMaker( getMaker() );
</code></pre>
<p>This new model maker will then be used to generate persistent
models named with the URI of the imported ontology, if it passed
instead of OntModelSpec.OWL_MEM_RULE_INF to the
createOntologyModel method of the model factory. Note that once the
import has been loaded once into the database, it can be re-used by
other ontologies that import it. Thus a given database will only
contain at most one copy of each imported ontology.</p>
<p><strong>Note on performance</strong> The built-in Jena reasoners, including the
rule reasoners, make many small queries into the model in order to
propagate the effects of rules firing. When using a persistent
database model, each of these small queries creates an SQL
interaction with the database engine. This is a very inefficient
way to interact with a database system, and performance suffers as
a result. Efficient reasoning over large, persistent databases is
currently an open research challenge. Our best suggested
work-around is, where possible, to snapshot the contents of the
database-backed model into RAM for the duration of processing by
the inference engine. An alternative solution, that may be
applicable if your application does not write to the datastore
often, is to precompute the inference closure of the ontology and
data in-memory, then store that into a database model to be queried
by the run-time application. Such an off-line processing
architecture will clearly not be applicable to every application
problem.</p>
<p>A <a href="TODO">sample program</a>
shows the above steps combined, to create an ontology in which both
base model and imports are stored in a persistent database.</p>
<h2 id="experimental-ontology-tools">Experimental ontology tools</h2>
<p>Starting with Jena release 2.6, the <code>OntTools</code> class provides a
small collection of commonly-requested utilities for assisting with
ontology processing. Given that this is a new feature, you should
regard it as an experimental facility for the time being. We
welcome feedback. The capabilities in <code>OntTools</code> are implemented as
static methods. Currently available tools are:</p>
<ul>
<li><code>OntClass getLCA( OntModel m, OntClass u, OntClass v )</code>
Determine the <em>lowest common ancestor</em> for classes u and v. This is
the class that is lowest in the class hierarchy, and which includes
both u and v among its sub-classes.</li>
<li><code>Path findShortestPath( Model m, Resource start, RDFNode end, Filter onPath )</code>
Breadth-first search, including a cycle check, to locate the
shortest path from <code>start</code> to <code>end</code>, in which every triple on the
path returns <code>true</code> to the <code>onPath</code> predicate.</li>
<li><code>List namedHierarchyRoots( OntModel m )</code>
Compute a list containing the uppermost fringe of the class
hierarchy in the given model which consists only of named classes.</li>
</ul>
</div>
</div>
</div>
<footer class="footer">
<div class="container" style="font-size:80%" >
<p>
Copyright &copy; 2011&ndash;2022 The Apache Software Foundation, Licensed under the
<a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.
</p>
<p>
Apache Jena, Jena, the Apache Jena project logo, Apache and the Apache feather logos are trademarks of
The Apache Software Foundation.
<br/>
<a href="https://privacy.apache.org/policies/privacy-policy-public.html"
>Apache Software Foundation Privacy Policy</a>.
</p>
</div>
</footer>
<script type="text/javascript">
var link = $('a[href="' + this.location.pathname + '"]');
if (link != undefined)
link.parents('li,ul').addClass('active');
</script>
</body>
</html>