Updates on RDF in abiword

From: Ben Martin <monkeyiq_at_users.sourceforge.net>
Date: Fri Sep 09 2011 - 02:49:04 CEST

Hi,
  As some of you know, I'm hacking some RDF support into abiword :)

  Firstly, Lint, sorry I keep missing you on IRC. I think there should
only be a few GUI elements which are only implemented in GTK2 (The
Editor and Query dialogs). If the context menu and RDF menu are #ifdef
commented out on windows builds would that make compilation simpler
again for you?

  Abiword now includes many new abicommands to load/query/save/test the
RDF of a document. AbiCommands include functionality such as inserting
new xml:id values into the document and getting the submodel for an
xml:id. These code paths call the same underlying code as the GUI during
normal program operation. I've tried to make most of the RDF code
available to abicommand.

  I have also expanded abicommand a little bit too, allowing the SPARQL
query execution to consume a multi line argument and some other new RDF
commands can now allow embedded "#" chars in their arguments etc. For
AbiCommand, I added a few new App level bools to turn off double
buffering and "NoGUI" so that code that uses cairo et al can quietly
fail rather than assert errors because the GUI is not realized. It is a
bit of a kludge, though luckily does not have a huge footprint in the
code. With these variables in place you can run a debug build of abiword
through the RDF tests without it failing or stopping at an assertion.

  I recently added Modal/Non Modal dialogs to the main abiword dialog
inheritance tree. Having these two allows things like the popup bubbles
for annotations and RDF to show and hide their popup window when dialogs
appear and disappear. This is not used by all dialogs yet, but when one
does inherit from one of these new classes then popup bubbles should do
the right thing automatically.

  I moved some boilerplate code from dialogs into these new
superclasses. They should be fairly easy to inherit from as they slot
into the parent tree of a dialog in a fairly easy way. For example
inherit from AP_Dialog_Modeless instead of XAP_Dialog_Modeless. The new
AP class has the XAP as it's parent so you get the same thing as before
with the additional code from the AP_Dialog_Modeless class too. The main
cleanup after changing the superclass is removing boilerplate code that
the new AP parent class already has and some changes like the window
title using a std::string instead of explicit memory allocations.

See for example:
AP_Dialog_Modeless::ConstructWindowName()
using a std::string also lets BuildWindowName() return the title instead
of taking a pointer to a carray to plump it into. The ap_Dialog_Lists
dialog inherits from the new Modeless superclass so popup bubbles for
annotations and rdf should hide when that dialog is in view.

  The new RDFModel_SPARQLLimited class is kind of cool IMHO. It is a
subclass of RDFModel so you can get at the triples with the same API as
the RDF for the document. The SPARQLLimited class takes another
RDFModel, the delegate, and returns the subset of the RDF from the
delegate which matches your SPARQL query. This is the class that allows
the RDFEditor to show all or a subset of the RDF. When you right click
an xml:id and there are 2+ in scope (like multi.odt from my plugtest
github), then the RDFEditor will show you a combo box letting you select
which xml:id(s) you want to see and edit the RDF for.

  Another little design I swiped from libferris is that RDFModels are
now versioned. You can only change an rdfmodel using a transaction
object like
PD_DocumentRDFMutationHandle h = model->createMutation();
h->add(a,b,c);
h->commit();
So the commit will bump the version of the model. This lets
RDFModel_SPARQLLimited optimize itself because it can tell if the RDF
has changed since it last executed the query. If no changes have
occurred it can happily just work with a local cache. From an API users
point of view this lets you loop over the RDFModel_SPARQLLimited model
using begin(), end(), operator++ etc and the query will only run once
during your code. Assuming the highly common case of no changes at the
same time as your read access.

This is the "Restrict to RDF Link" in the 4th image from this post
http://monkeyiq.blogspot.com/2011/08/rdf-low-level-interaction-in-abiword.html

I have called xml:ids "RDF Links" in the GUI because it seems a bit less
intimidating. There is also the side effect that xml:ids might be used
for other tasks so making it an RDF Link means you really want a way to
link document content to RDF and the converse.

http://monkeyiq.blogspot.com/2011/08/rdf-linking-in-abiword.html

  I have added a new "rdf" directory to my test suite on github which
contains a number of tests to verify the RDF system;
https://github.com/monkeyiq/odf-2011-track-changes-tests/blob/master/rdf/RDF.pm

This uses a little bit of Perl and Expect to control AbiCommand from the
suite;
https://github.com/monkeyiq/odf-2011-track-changes-tests/blob/master/abicommand.pl
While expect is a little bit of overkill at current, most of the tests
just acsend() a command and acmatch(regex) to verify the results are /
aren't as expected. Using the wrappers does add a little too, for
example acsend() ensures that OK is received from AbiCommand before
returning, so a test will fail if the command itself is unhappy
irrespective of if it gives the desired output. On the plus side, the
perl expect module brings it's nice timeout handling etc and allows for
more complex interactions in the future.

  Some of the new tests I'm quite happy with. For example, test9submodel
tests the SPARQL based submodel code mentioned above. Not only that but
the test9 goes on to create a mutation, commit it, and verify the
result. A mutation on a submodel for RDF associated with an xml:id will
automatically associate any new RDF triples with that xml:id for you.
Likewise, removing the last triple to reference the xml:id will remove
The link to that xml:id for you. For example, in the final block of
test9 the triple
uri:subj1 uri:pred1 literalvalue1
is removed which causes abiword to remove the associating triple:
uri:subj1
http://docs.oasis-open.org/opendocument/meta/package/common#idref wingb
automatically. This the contains test and acmatch for "0" for the idref
triple in the test suite.

  The insertion and deletion of xml:id links is tested in test7 and the
new RDF/XML import/export code in test8. I should perhaps rename that
git repository "abiword-tests" as it expands to cover more aspects of
the code. Two new functions in here for RDFXML file verification, at the
bottom of the file...
https://github.com/monkeyiq/odf-2011-track-changes-tests/blob/master/common.pl

In summary, there are now two new dialogs, the RDF Editor and RDF Query
windows, expansion of the "Goto" dialog to allow one to jump to an
xml:id, many improvements to the RDF API in pd_DocumentRDF.cpp, a whole
bunch of new abicommands to access most of the RDF functionality from
the console via AbiCommand, and of course the PD_RDFQuery class with the
simple interface below. Behind the scenes PD_RDFQuery hooks a custom
storage backend into redland at abiword_storage_factory() which allows
SPARQL query evaluation directly against any abiword RDF model
(PD_RDFModelHandle).

The public API is nice and simple:

class ABI_EXPORT PD_RDFQuery
{
public:
   PD_RDFQuery( PD_DocumentRDFHandle rdf,
                PD_RDFModelHandle m = PD_RDFModelHandle() );
   PD_ResultBindings_t executeQuery( const std::string& sparql );
};

Here, the optional RDFModelHandle allows you to execute against just a
submodel of all the RDF for the document. For example, only the RDF
associated with two or three xml:id links in the document.

Oh, and I added a little Drag and Drop example of creating RDF from the
desktop:
http://monkeyiq.blogspot.com/2011/09/abiword-rdf-drag-and-drop.html

Received on Fri Sep 9 02:49:20 2011

This archive was generated by hypermail 2.1.8 : Fri Sep 09 2011 - 02:49:20 CEST