the reification SPI in Jena 2

author: Chris Dollin
version: 1.0
date: 1st May 2003

1. introduction

This document describes the reification SPI, the mechanisms by which the Graph family supports the Model API reification interface.

Graphs handle reification at two levels. First, their reifier supports requests to reify triples and to search for reifications. The reifier is responsible for managing the reification information it adds and removes - the graph is not involved.

Second, a graph may optionally allow all triples added and removed through its normal operations (including the bulk update interfaces) to be monitored by its reifier. If so, all appropriate triples become the property of the reifier - they are no longer visible through the graph.

A graph may also have a reifier that doesn't do any reification. This is useful for internal graphs that are not exposed as models. So there are three kinds of Graph:

2. Graph operations for reification

The primary reification operation on graphs is to extract their Reifier instance. Handing reification off to a different class allows reification to be handled independantly of other Graph issues, eg query handling, bulk update.

graph.getReifier() -> Reifier

Returns the Reifier for this Graph. Each graph has a single reifier during its lifetime. The reifier object need not be allocated until the first call of getReifier().

add(Triple), delete(Triple)

These two operations may defer their triples to the graph's reifier using handledAdd(Triple) and handledDelete(Triple); see below for details.

3. interface Reifier

Instances of Reifier handle reification requests from their Graph and from the API level code (issues by the API class ModelReifier.

reifier.getHiddenTriples() -> Graph

The reifier may keep reification triples to itself, coded in some special way, rather than having them stored in the parent Graph. This method exposes those triples as another Graph. This is a dynamic graph - it changes as the underlying reifications change. However, it is read-only; triples cannot be added to or removed from it.

The SimpleReifier implementation currently does not implement a dynamic graph. This is a bug that will need fixing.

reifier.getParentGraph() -> Graph

Get the Graph that this reifier serves; the result is never null. (Thus the observable relationship between graphs and reifiers is 1-1.)

class AlreadyReifiedException

This class extends RDFException; it is the exception that may be thrown by reifyAs.

reifier.reifyAs( Triple t, Node n ) -> Node

Record the t as reified in the parent Graph by the given n and returns n. If n already reifies a different Triple, throw a AlreadyReifiedException.

Calling reifyAs(t,n) is like adding the triples:

to the associated Graph; however, it is intended that it is efficient in both time and space.

reifier.hasTriple( Triple t ) -> boolean

Returns true iff some Node n reifies t in this Reifier, typically by an unretracted call of reifyAs(t,n).

The intended (and actual) use for hasTriple(Triple) is in the implementation of isReified(Statement) in Model.

reifier.getTriple( Node n ) -> Triple

Get the single Triple associated with n, if there is one. If there isn't, return null.

A node reifies at most one triple. If reifyAs, with its explicit check, is bypassed, and extra reification triples are asserted into the parent graph, then getTriple() will simply return null.

reifier.allNodes() -> ExtendedIterator

Returns an (extended) iterator over all the nodes that (still) reifiy something in this reifier.

This is intended for the implementation of listReifiedStatements in Model.

reifier.allNodes( Triple t ) -> ClosableIterator

Returns an iterator over all the nodes that (still) reify the triple _t_.

reifier.remove( Node n, Triple t )

Remove the association between n and the triplet. Subsequently, hasNode(n) will return false and getTriple(n) will return null.

This method is used to implement removeReification(Statement) in Model.

reifier.remove( Triple t )

Remove all the associations between any node n and t; ie, for all n do remove(n,t).

This method is used to implement removeAllReifications in Model.

handledAdd( Triple t ) -> boolean

A graph doing reification may choose to monitor the triples being added to it and have the reifier handle reification triples. In this case, the graph's add(t) should call handledAdd(t) and only proceed with its add if the result is false.

A graph that does not use handledAdd() [and handledDelete()] can only use the explict reification supplied by its reifier.

handledRemove( Triple t )

As for handledAdd(t), but applied to delete.

4. SimpleReifier

SimpleReifier is an implementation of Reifier suitable for in-memory Graphs built over GraphBase. It operates in either of two modes: with and without triple interception. With interception enabled, reification triples fed to (or removed from) its parent graph are captured using handledAdd() and handledRemove; otherwise they are ignored and the graph must store them itself.

SimpleReifier keeps a map from nodes to the reification information about that node. Nodes which have no reification information (most of them, in the usual case) do not appear in the map at all.

Nodes with partial or excessive reification information are associated with Fragments. A Fragments for a node n records separately

If the Fragments becomes singular, ie each of these sets contains exactly one element, then n represents a reification of the triple (S, P, O), and the Fragments object is replaced by that triple.

(If another reification triple for n arrives, then the triple is re-exploded into Fragments.)