Thursday, August 18, 2011

RDF Low Level Interaction in Abiword

I've recently mentioned creating and jumping to the RDF Links (xml:id to RDF bridging) in Abiword. I also had a work in progress dialog to allow SPARQL Query execution. Things are moving along quite nicely and the RDF subsystem continues to get stronger with a Triple Editor and updates to the SPARQL dialog shown below and execution support.

Shown below is the new RDF Editor dialog. The file menu allows you to import and export RDF/XML files into the document. The Triple menu has the same actions as the toolbar; new, copy, and delete. Shown at the bottom of the dialog is the total number of RDF triples for this document. Clicking on a cell in the table lets you edit it and you can use the existing URI prefixes if you like, for example rdf:type instead of the full URI. I have to allow configuration of those prefixes yet.

When you select some text in Abiword you can use Insert/RDF Link to create a new RDF link for that text. This is much like making a bookmark, hyperlink and other items.

The context menu for an RDF link allows you to edit the RDF associated with link. That window is shown below. There can be many RDF links in scope at any location in the document. Consider the case where a paragraph has RDF linked to it and a sentence and word does too. So when you bring up the RDF editor window from the context menu of an RDF link you get a combo box letting you select which links you want to see the RDF associated with.

By default the editor shows you all the RDF Links that are in scope where the cursor was located when you opened the dialog from the context menu. In this case widetime is an RDF link for the whole paragraph and wingb is for three words at the end of the paragraph. The dialog shows you the triples that link the subjects to this location: those with ?subject pkg:idref widetime. Selecting a different RDF link from the combo box restricts the triples shown to be only those associated with the RDF link you have chosen.

I decided to make the dialog automatically link any new triples you create or edit to the RDF link you have specified in the combo box. If there is more than one RDF link shown then the first link is used for new and updated triples.

This allows you to select some text, create an RDF link, right click the link and "Show RDF" from the context menu and start adding and editing triples and Abiword will automatically associate all those shown with the RDF link you have selected. Yay, full, low level RDF support with a GUI ;)

In case you have forgotten the scope of an RDF link in the document, the RDF editor will select the scope in the main document when you select a triple in the editor. I might make that functionality have a toggle button in the toolbar instead of making it happen automatically all the time.

One of the plugins that comes with Abiword is the "AbiCommand" which gives you a console interface to Abiword. You can start it from the shell using:

$ abiword --plugin AbiCommand
AbiWord command line plugin: Type "quit" to exit

I have added some new RDF commands to the AbiCommand plugin which allows fairly good interaction with RDF from the command line. The context-model commands allow you to set and interact with a submodel of all the RDF in the document. For example, only the RDF that is associated with a given xml:id. All updates to RDF happen via a mutation object. So you first use rdf-mutation-create, then add/remove as desired and complete things with rdf-mutation-commit. For those who are still reading now, see pd_DocumentRDF.h in the C++ source code and you'll notice createMutation() in the model, with add(), remove(), commit() and rollback() methods. The new commands in AbiCommand are shown below:

...RDF subsystem...      

Where a function reads RDF, it will try to use the RDF context model if it is set
Otherwise the entire RDF for the document is used.
An RDF context is obtained using rdf-set-context*
and cleared with rdf-clear-context-model

rdf-import <src> - load all RDF from an RDF/XML file at <src> into the document
rdf-export <dst> - save all document RDF to an RDF/XML file at <dst>
rdf-clear-context-model - RDF can at times use a context model which is a subset of
all the RDF associated with the document.
This command clears that and uses all the RDF again.
rdf-set-context-model-pos <pos> - Use a context model with the subset of RDF
associated with the given document position
rdf-set-context-model-xmlid <xmlid> [readxmlid1,readxmlid2]
- Use a context model with the subset of RDF
associated with the given document xml:id value
rdf-context-show-objects <s> <p> - Show the object list for the given subject,predicate pair
rdf-context-show-subjects <p> <o> - Show the subject list for the given predicate,object pair
rdf-context-contains <s> <p> <o> - True if the triple is there.
rdf-context-show-arcs-out <s> - Show the predicate objects associated
with the given subject
rdf-get-xmlids - Get a comma separated list of the xml:ids assocaited
with the current cursor location
rdf-get-all-xmlids - Get a comma separated list of all the xml:ids
rdf-get-xmlid-range <xmlid> - Show the start and end document position associated
with the given <xmlid>
rdf-movept-xmlid-start <xmlid> - Move the cursor location to the start of the range
for the given xml:id value
rdf-movept-xmlid-end <xmlid> - Move the cursor location to the end of the range
for the given xml:id value
rdf-uri-to-prefixed <uri> - Convert full uri to prefix:rest
rdf-prefixed-to-uri <uri> - Convert prefix:rest to full uri
rdf-size - Number of RDF triples for context
rdf-mutation-create - Start a RDF mutation for the document
rdf-mutation-add <s> <p> <o>- Add the given triple to the current mutation
rdf-mutation-remove <s> <p> <o>- Remove the given triple in the current mutation
rdf-mutation-commit - Commit current RDF mutation to the document
rdf-mutation-rollback - Throw away changes in current RDF mutation
rdf-execute-sparql - Execute SPARQL query against RDF context
rdf-xmlid-insert <xmlid> - Insert xml:id for current selection
rdf-xmlid-delete <xmlid> - Delete the xml:id from the document

Some examples of AbiCommand interaction are shown below to give a little idea of use. These are using the multi.odt from my plugtest github repository.

load       /tmp/multi.odt

rdf-export /tmp/output.rdf
rdf-import /tmp/extra.rdf

rdf-set-context-model-pos 1006
rdf-export /tmp/1006.rdf

rdf-set-context-model-xmlid wingb
rdf-export /tmp/wingb.rdf

rdf-export /tmp/all.rdf

rdf-get-xmlid-range wingb

rdf-execute-sparql "prefix rdf: <>
prefix foaf: <>
prefix pkg: <>
prefix geo84: <>

select ?s ?p ?o ?rdflink
where {
?s ?p ?o .
?s pkg:idref ?rdflink .
filter( str(?rdflink) = \"wingb\" || str(?rdflink) = \"widetime\" )

load /tmp/multi.odt
movept +27
movept +4
rdf-xmlid-insert foo
save /tmp/updated.odt

load /tmp/multi.odt
rdf-context-contains uri:wingb rdf:type
rdf-context-show-objects uri:wingb rdf:type
rdf-context-show-subjects rdf:type
rdf-context-show-arcs-out uri:wingb

Tuesday, August 2, 2011

RDF Linking in Abiword

Another minor step forward in the quest to make the RDF facility in ODF more useful to document authors... Abiword can now create links to RDF and you can jump to these links in a similar manner to how bookmarks work. The upside to using RDF links over bookmarks is that you can associate meaning with the RDF links. So for example, the text "Barry" can be associated with his vcard and possibly normal work geolocation.

Making a new RDF link is just like inserting a bookmark:
And the "Go To..." dialog now offers RDF links as first class citizens. I did a little tweaking to this goto window while I was at it; moving things into a paged configuration and abstracting out some common code into utility functions.

On the API front, there are now STL like iterators for the RDF and that theme will be present in the query results engine and perhaps also in the arcsOut() API. Speaking of querying, the window for SPARQL is coming along. I'll start working on the actual query execution shortly. Notice that the RDF triples are shown with namespaces in effect so you get something more readable.

As I mentioned in my previous post, the purple links can be turned on and off to highlight parts of the document with RDF associated. Using a special menu item you can pull up the SPARQL query dialog with a preformed query to show just the RDF associated with the current cursor location.

I admit that some of this is quite low level, for example directly inspecting the triples for the cursor position. But full disclosure isn't a bad thing right? I syndicated this to planet KDE because Calligra handles RDF too. Hopefully posts about RDF are interesting to hackers regardless of the desktop platform :)