ioctl
A discussion of the design and implementation of an RDF API.
The following forms are supported:
model.assert(RDFResource, RDFProperty, RDFNode); model.assert(TripleIterator);
The latter form takes 'ownership' of the TripleIterator; in other words, it calls dispose() on the iterator after it's done with it. The reason for this is notational convenience - we can write:
model1.assert(model2.confirmAndReturn(s, p, o)); model2.confirmAndReturnInto(s, p, o, model1); // Equivalent
and not have any resources to clean up. There are better ways, possibly of doing this (confirmAndReturnInto, as shown) but this stays around as a convenience method.
We support wildcards as a basic necessity. In the Java implementation, a wildcard is signified by using null for the subject, predicate, or object property.
Again, remove variants may support the returning of deleted arcs.
Again, we support wildcards. The confirm call on its own merely returns a boolean value indicating whether an arc (or more than one) matching the given pattern exists in the model.
The confirmAndReturn* calls actually supply the details of which arcs fit the given pattern.
What these transformations imply in terms of the formal model.
Used as follows:
RDFModel model;
// ...
for (TripleIterator i = model.confirmAndReturn(null, null, null);
! i.eof();
i.next())
{
// Do stuff with i.getSubject(), i.getPredicate(), i.getObject()
}
The TripleIterator fits more naturally into a for-loop than a while; this doesn't sit well with the Java iterator idioms. Fixable.
Used as follows:
RDFModel model; RDFModel newmodel = model.confirmAndReturnModel(s, p, o);
There is an obvious implementation, and an obvious place where this can be improved upon (views, recordsets, snapshots... anything that relies on an underlying RDBMS)
Used as follows:
RDFModel model; // The thing we're querying RDFModel newmodel; // The place we'll be storing the results // ... model.confirmAndReturnInto(s, p, o, newmodel);
Actually, while many of these operations are useful, and however hard it might be to envisage the use of an RDFModel that we cannot use the confirm* functions on, any of these triple-based operations may remain unimplemented by a particular model.
Obviously, if a model supports one style of *AndReturn* it's trivial to get it to implement all of them. But some operations may be unimplemented. This should be discoverable by the user of an RDFModel through some mechanism (eg, in Java, by having the RDFModel implement a number of 'flag' interfaces, and/or having the RDFModel throw appropriate exceptions).
Why should we ever want a model that we can't confirm or retract from, but can assert into? This seems odd, but imagine an implementation of RDFModel, OutputStreamRDFModel, that pretty much does what it says: triples asserted into it are written to some output stream. It may neither keep sufficient state to respond convincingly to confirm* calls, nor be in a position to offer retract* operations.
Similar arguments can be made for missing out assert* (read-only models?) etc.
These kinds of considerations can be applied to the whole gamut of operations that we mention here; the point is raised now because it seems an appropriate stage to do so.
TODO: mention CatenateIterator, TeeIterator, FilterIterator, etc.