Subscribe

VRM with FOAF + OpenID

A quick note-to-self. I’m currently working on some other FOAF + OpenID stuff, so this is nearby enough that I might well put together a demo in the near future…but not today.

Tim Bray discusses Changing your address in the context of Vendor Relationship Management, prompted by “Feeds-Based VRM”: A Web-Centric Approach to VRM Implementation. The question is how you keep a vendor (or other contact) aware of your current address.

I came to the same conclusion as Tim, that feeds aren’t really necessary for this kind of thing, the data can be put directly on the Web and the contact given the appropriate URI. In comments over there I pointed to Tim Berners-Lee’s Give yourself a URI - an online FOAF profile solves most of the problem. The part it doesn’t solve is access control - you might not want to make your address public. But with the help of linked data, off-the-shelf tools and a little scripting, this is pretty easy to fix.

First of all, looking at how you might represent this information, vCard is the dominant model for this kind of info. Whether that’s expressed in the original vCard format or hCard or RDFa or RDF/XML doesn’t really matter. These can all be mapped to the RDF model, which is key to what follows… Here’s the relevant bit of a vCard in Turtle syntax (first pass, probably not 100% correct):

prefix : <http://www.w3.org/2006/vcard/ns#> .
[ a :VCard;
:agent <#me>
:homeAdr [
a :Address;
:street-address "7, Mozzanella" ;
:country-name "Italy"
] ;
]

Now I could just dump this in my public FOAF profile at, say http://example.org/public/me. But because I want the address to be restricted, I’ll separate the information (following the principles of linked data) like this -

in http://example.org/public/me -

prefix : <http://www.w3.org/2006/vcard/ns#> .
[ a :VCard;
:agent <#me>
:homeAdr <http://example.org/restricted/myaddress> .
]

and in <http://example.org/restricted/myaddress> :

prefix : <http://www.w3.org/2006/vcard/ns#> .
<> a :Address;
:street-address "7, Mozzanella" ;
:country-name "Italy" .

Now I need to wrap the latter part in authentication/authorization. Traditionally I might hard-code a list of who can see this data, but there’s a neater way. Somewhere I’ll put statements like the following (with proper URIs as appropriate):

<#me> foaf:knows [
<personA> foaf:openid <personAopenID>
]
<#me> x:businessContact [
<personB> foaf:openid <personBopenID>
]
<#me> x:businessContact [
<personC> foaf:openid <personCopenID>
]
<#me> x:businessContact [
<personD> foaf:openid <personDopenID>
]

Anyone wishing to see the restricted info will be asked for their OpenID URI. Whether they can see a particular resource can be governed by simple rules, for example expressed through string-templated SPARQL queries:

SELECT ?person
WHERE {
?person foaf:openid $openid$ .
OPTIONAL { <#me> foaf:knows ?person }
OPTIONAL { <#me> x:businessContact ?person }
}

Ok, that’s very sketchy, but hopefully gives the idea. To be properly declarative in practice you’d probably want to put the access rules in a separate chunk of RDF, and query across the whole lot. But given decent libraries (e.g. the OpenID PHP lib worked pretty much out of the box for me, and ARC is a really straightforward PHP RDF toolkit), we’re talking about maybe a days work to write and deploy the scripts - which could be used by anyone else with regular PHP-capable hosting.

A Web-centric approach to VRM should use the Web, and as Berners-Lee himself recently put it:

Linked Data is the Semantic Web done as it should be. It is the Web done as it should be.

Ad hoc plumbing

Half an hour ago I discovered microrevie.ws, a Twitter-based review site. I couldn’t resist a quick play.

Like twitcrit 1.1 [currently not working *] and twitcrit 2.0, these reviews are authored in Twitter using a few (different) conventions. The microrevie.ws page is HTML with embedded microformats, which made me think right away of GRDDL. There were a couple of slight snags - the HTML isn’t XHTML its HTML5, and the page doesn’t declare HTML Meta Data profiles for the microformats. So here we go…

  1. live microrevie.ws page
  2. (1) piped through an online HTML Tidy service to yield a XHTML version
  3. (2) with a simple XSLT applied to insert @profile, using an online XSLT service to yield GRDDL-friendly XHTML
  4. (3) sent through triplr.org to yield RDF - here in Turtle syntax

Look ma…no import/export!

I’m pretty sure the GRDDL transformations aren’t 100% complete/accurate, and I couldn’t find one for hAtom which is used in the source, but there’s enough to show a lot of triple, generated live from the source simply by hooking together the URIs. Check this -
http://triplr.org/turtle/http://www.w3.org/2000/06/webdata/xslt?xslfile=http%3A%2F%2Fhyperdata.org%2Fxslt%2Fprofiles.xsl&xmlfile=http%3A%2F%2Fcgi.w3.org%2Fcgi-bin%2Ftidy%3FdocAddr%3Dhttp%253A%252F%252Fmicrorevie.ws%252F%26forceXML%3Don&transform=Submit

Not exactly the kind of thing you’d want on your business card, but it is bookmarkable/linkable.

Oh yeah - want a visualization with that? Flip triplr.org to /rdf/ and try it on the RDF Validator : http://www.w3.org/RDF/Validator/ARPServlet?URI=http%3A%2F%2Ftriplr.org%2Frdf%2Fhttp%3A%2F%2Fwww.w3.org%2F2000%2F06%2Fwebdata%2Fxslt%3Fxslfile%3Dhttp%253A%252F%252Fhyperdata.org%252Fxslt%252Fprofiles.xsl%26xmlfile%3Dhttp%253A%252F%252Fcgi.w3.org%252Fcgi-bin%252Ftidy%253FdocAddr%253Dhttp%25253A%25252F%25252Fmicrorevie.ws%25252F%2526forceXML%253Don%26transform%3DSubmit&PARSE=Parse+URI%3A+&TRIPLES_AND_GRAPH=PRINT_BOTH&FORMAT=PNG_EMBED

(scroll down towards the bottom & right to see the graph - it’s a bit big)

Should work in the Tabulator too.

Incidentally, there’s a neat trick at microrevie.ws: the subject of reviews gets posted to twitter as a simple string (ending with a ‘;’) but gets turned into a URI, e.g.
http://microrevie.ws/reviewables/Sparks+Alcoholic+Caffeinated+Beverage

Could come in handy for those times you really want a literal as the subject of a triple. Right now microrevie.ws has Google hooked up to help you find out what the thing is. Making that more explicit seems like it might be a job for Open Linking Data

* I’m pretty sure there won’t be much difference in complexity of the operational code between twitcrit 1.1 and twitcrit 2.0. One possible explanation for the reason the latter is still running (even though I haven’t looked at it in months) and the former isn’t might be that the code proper in the working version is just a simple bit of Python, loosely coupled to some Software as a Service doing storage + SPARQL elsewhere (it’s on the Talis Platform). If I’d had to run that bit of infrastructure myself, I doubt very much whether that’d still be running.

Import/export and the Web

A post on the Open Data Definition list from Ben Werdmuller asks an interesting question - is syndication an easier sell than import/export?

Ok, background first: Open Data Definition is a proposed format for transfer of data between systems, with DataPortability in mind. In many respects it’s a ‘lite’ reinvention of RDF, targeted at the average Web developer. While I and others might question the underlying assumption that RDF is too difficult for typical Web developers, and perhaps express a little gut-reaction pushback, there’s nothing inherently wrong with something like this if it fills a (possibly significant) niche, and plays nicely with other Web standards. Design-wise, there is a sanity check which can be applied, the Test of Independent Invention :

If someone else had already invented your system, would theirs work with yours?

Does/could RDF work with ODD? - well, nearly. Yes, because it should be reasonably straightforward to map between RDF graphs and ODD’s format (there’s an interesting little complication in its indirection of metadata that’d take a bit of figuring, but bashing it with SPARQL & XSLT for a while would probably suggest a good approach). It fails right now because ODD doesn’t as yet allow for transparent interpretation, not having an XML namespace, hence not really placing itself on the global Web. Any automatic conversion would have to be done by sniffing the content - an agent needs complete prior knowledge. [If the ODD folks are willing to give the format a namespace, I’ll volunteer to sort out the mappings & GRDDL bits]. Hmm, I wonder if they’ve tried nesting ODD in other XML formats yet…

Anyhow, back to Ben’s question. I think he has a point - syndication should be a relatively easy sell these days because of RSS/Atom. But marketing aside, there are several different ways to get the data from system A to system B:

  1. import/export where the data is transferred through an intermediary (i.e. the desktop)
  2. one-off direct transfer (system B does a GET to system A)
  3. polling - traditional syndication, periodic transfer
  4. linkage - lazy polling, any transfer happens on demand

At this point in time, the first of these isn’t exactly Web-friendly, typically requiring a human intermediary for its operation. In future, with smarter clients maintaining a local cache of data, something like this might make more sense. Such clients could be acting as proxies for any of the other modes of connection. But let’s assume this kind of capability’s already here. If you stand back, the same thing is happening in all these cases - the receiver will be given an identifier for the resource of interest (the profile data or whatever) and can use HTTP on it as appropriate. This is completely independent to what’s in the data itself - even though RSS/Atom formats contain a series of time-stamped entries, the way they get processed is up to the consumer. These different modes are orthogonal to authentication/authorization and privacy or copyright issues. Each is, in its own way, using linked data. To get more information about something, the consumer follows its nose and dereferences the URIs. ‘Course if you bring message content into the equation and/or allow an arbitrary number of agents in the interaction, the number of possible modes explodes.

So yeah, ok, what point am I trying to make here…dunno, it just seems somehow significant that questions like “syndication or import/export?” should arise, given the underlying infrastructure. More telling of the silo nature of many current Web systems - themselves generally products of a pre-Web mindset - than anything to do with the Web itself. This too shall pass, as they say.

See also: Walled gardens: mapping the parties

PS. Reminds me - in my little DP video I had a mockup of a “Connect!” button. It was only a mockup because of the deadline for videos, the implementation I had in mind being essentially OpenID + HTTP GET + SPARQL CONSTRUCT

Openings For Senior Developers

We have some openings for Senior Developers at Talis in the Platform development group. Talis is a mature and solid business based in the UK and provides a unique mix of loyal customers, amazing innovation and a focus on the long term.

Our platform development group is responsible for making sure that the Talis Platform is the premier environment for developing and delivering great Semantic Web applications. We need your help in designing and building our infrastructure to support hundreds of thousands of users and their data. We’re looking for people who:

  • use their code to communicate their ideas clearly
  • are proficient in Java and comfortable in Python, PHP and other scripting languages
  • can break dependencies and decompose hard problems into simpler ones
  • never forget about scalability, performance and security
  • prefer to develop test first
  • have spent time modelling data in RDF
  • can develop solutions to problems, communicate them to the team and get them implemented quickly
  • aren’t afraid to ask questions
  • have implemented HTTP clients and servers
  • like to say “let’s try it” and “we can do that”
  • understand how to balance perfection with reality
  • are as happy to lead as to follow
  • know when to reuse and when to start afresh
  • can tell us about something new they learned this year

How to apply:

Take a look at the problems below and select two to answer. Please send us your C.V and an application
letter including your answers to careers@talis.com

  • The Web can be modelled as a network of nodes labelled with URLs and connected by directed arcs.
    Suppose we want to find all the URLs linked to and from any given URL, and all the URLs that are
    linked from any two given URLs. What kind of data structures might be suitable for representing and
    querying a network with 10^8 nodes each having between 10 and 50 arcs?
  • Discuss the different types of automated testing that are needed to maintain high quality software.
    What kinds of programming language are best suited to each type of testing? What techniques could be
    used for testing asynchronous processes and for processes that operate over large volumes of data? Are
    there any situations that you wouldn’t test?
  • Large-scale systems composed of many cooperating application servers often need to share and cache
    configuration. Suppose any server can initiate changes that need to be reflected in real time to the other
    application servers in the cluster. What strategies could you use for coordinating this kind of behaviour
    and how are they tolerant to various failure conditions?

Moriarty Version 1.0

Tonight Moriarty turns 1.0. We’re starting to use Moriarty more seriously within Talis so we need some discipline around its development. To help this I’ve formally tagged the current version of Moriarty as 1.0. The intention is that all versions of Moriarty with the same major version number will be backwards compatible, so version 1.5 will be a drop in replacement for 1.0. Version 2.0, however, might see us introduce some breaking changes. We’ll try to avoid that of course but often it’s inevitable

You can download the latest release: moriarty-1.0.tgz or you can check it out of subversion using http://n2.talis.com/svn/playground/iand/moriarty/tags/1.0/. The trunk is still the bleeding edge and can be found here: http://n2.talis.com/svn/playground/iand/moriarty/trunk/

About Moriarty… Moriarty is a simple PHP library for accessing the Talis Platform. It follows the Platform API very closely and wraps up many common tasks into convenient classes while remaining very lightweight. It also provides some simple RDF classes that are based on the excellent ARC2 class library. Moriarty is primarily being developed by Ian Davis and is in continual alpha, subject to occasional rapid bursts of change. You can read more about Moriarty on the n² wiki and get its source from the n² subversion repository

Breaking Changes for Moriarty

As I alluded to earlier I have made some breaking changes to Moriarty (now in subversion as revision 657). These changes are to the index structure used by SimpleGraph which make it compatible with the RDF/PHP Specification. Most of the effects will be internal to Moriarty but some applications may be using the index directly via the get_index method.

I think these are the last breaking changes needed for the foreseeable future so this is probably going to be version 1.0. More on that and versioning policy in a while.

Specifically the changes to the index structure are:

  • The val key is renamed to value
  • The dt key is renamed to datatype
  • The type key now takes values of uri | bnode | literal instead of iri | bnode | literal

About Moriarty… Moriarty is a simple PHP library for accessing the Talis Platform. It follows the Platform API very closely and wraps up many common tasks into convenient classes while remaining very lightweight. It also provides some simple RDF classes that are based on the excellent ARC2 class library. Moriarty is primarily being developed by Ian Davis and is in continual alpha, subject to occasional rapid bursts of change. You can read more about Moriarty on the n² wiki and get its source from the n² subversion repository

Moriarty Facets

The latest batch of changes to Moriarty made it into subversion at the end oflast week (svn revision 655). The main change is the addition of a new FacetService class. You use it in the usual way. Either indirectly via the Store:

$store = new Store("http://api.talis.com/stores/mystore");
$fs = $store->get_facet_service();

Or directly if you know its URI:

$fs = new FacetService("http://api.talis.com/stores/mystore/service/facet");

Using the FacetService class is pretty simple: just call the facets method passing in the query, an array of fields to facet on and optionally the number of terms to return for each facet. As usual this method returns an HttpResponse:

$response = $fs->facets('query', array('field1','field2'));
if ($response->is_success()) {
  // do something useful
}
else {
  // mummy...
}

You can parse the XML response using the parse_facet_xml method which returns a nested array of data representing the facet data:

array (
  'field1' => array (
        0 => array ( 'value' => 'term1', 'number' => '5' ),
        1 => array ( 'value' => 'term2', 'number' => '4' ),
        1 => array ( 'value' => 'term3', 'number' => '2' ),
       ),
  'field2' => array (
        0 => array ( 'value' => 'term4', 'number' => '5' ),
        1 => array ( 'value' => 'term5', 'number' => '4' ),
        1 => array ( 'value' => 'term6', 'number' => '2' ),
       ),
) 

If you like living dangerously then you can combine both the previous steps into one using facets_to_array. If an error occurs this method simply returns an empty array:

$facets = $fs->facets_to_array('query', array('field1','field2'));

That’s it. A simple class for a simple but powerful service. You can read more about the Facet Service on the n² wiki.

There are a couple of big changes that I want to make pretty soon and I’m giving a heads up here because they may not be backwards compatible. The version of ARC I’m using is quite out of date (January 2008) so I need to update to the latest version. I’m not sure what that will involve. Maybe it’ll be completely smooth with no significant changes needed.

The second change is needed to make SimpleGraph’s index compatible with our RDF/PHP specification. I can see at least one major breaking change: I need to rename the hash key “val” to “value”. That is a pretty major breakage but I want to make Moriarty compatible with the RDF/PHP spec and with ARC2. I’m going to try and do that very soon.

About Moriarty… Moriarty is a simple PHP library for accessing the Talis Platform. It follows the Platform API very closely and wraps up many common tasks into convenient classes while remaining very lightweight. It also provides some simple RDF classes that are based on the excellent ARC2 class library. Moriarty is primarily being developed by Ian Davis and is in continual alpha, subject to occasional rapid bursts of change. You can read more about Moriarty on the n² wiki and get its source from the n² subversion repository

GRDDLing DeWitt’s Friends

DeWitt Clinton has a great write-up of Creating a HTML “friends” page from a Google Reader subscription list, a bit of hackery which leads to a hCard microformat-enriched friends list. A little tweak to the HTML can make it more machine-friendly, just adding a HTML Meta Data profile URI:

<head profile="http://www.w3.org/2006/03/hcard">

That profile is GRDDL-enabled, so any GRDDL-aware agent can interpret the source document as RDF. This part’s easy to demonstrate, thanks the online W3C GRDDL service. So I’ve put a tweaked version of the HTML online, and here’s DeWitt’s friends page as RDF (in Turtle syntax, rendered a little verbosely).

Having set this up I realised the data wasn’t actually expressing the friend relationship, so went on to put together some SPARQL to sort that out - below. But afterwards I realised that DeWitt’s HTML was actually expressing the relationships using XFN class names, but again without the profile URI to make it machine-friendly. So another tweak:

<head profile="http://www.w3.org/2006/03/hcard http://www.w3.org/2003/g/td/xfn-workalike">

- the corresponding service output (scroll down to see the extra bits). I suppose I should mention that you can have as many space-separate profiles as you like, and the GRDDL-aware agent will interpret them independently, just accumulating all the triples. The second profile URI adds xfn:friend relationships, I think it would have been more useful with foaf:knows as well, but it is only a demo.One of these days the microformats folks might get around to tweaking the official profile appropriately…

The SPARQL I mentioned looks like this:

prefix rdf:
prefix vcard:
prefix foaf:

CONSTRUCT
{
[ a foaf:Person;
foaf:homepage ;
foaf:name "DeWitt Clinton" ;
]
foaf:knows
[ a foaf:Person;
foaf:homepage ?homepage ;
foaf:name ?name ] .
}
WHERE
{
[ a vcard:VCard ;
vcard:url ?homepage ;
vcard:fn ?name ]
}

- when applied to DeWitt’s data (as RDF), this will map it across from the vCard vocabulary - finding the appropriate ?variables by matching the pattern in the WHERE clause, inserting those ?variables into the CONSTRUCT clause to produce some new RDF.

I tried this on the Redland SPARQL demo, and I think it’s producing the RDF I wanted. Unfortunately the serialization is really ugly - lots of bnodes, and it’s hard to check visually. It appears to confuse Tabulator too, and the W3C RDF Validator which is handy for this kind of visualization appears to be down. (Here’s a copy of the RDF/XML). Still, it was only a workaround - with the right profiles in place it’s not needed.

I’m not sure if there’s a microformat way of expressing that the source data was a subscription/reading list. To get the richest RDF out it might be easier to do what DeWitt did, but to a full RDF serialization rather than microformatted HTML (which is effectively a CustomRdfDialect), producing something like Planet RDF’s blogroll.

Tutorial: jQuery and the Talis platform

We will use the jQuery.Talis plugin to create a simple html+js interface to a talis store.

the Talis plugin is a small wrapper that simplifies retrieving json from the platform remotely (via jsonp). It allows you to query the platform, and specify callback functions for dealing with the retrieved data.

We’ll have a text box to type a search string into; this will retrieve results (of matching resource descriptions) from the platform store, and display them in a list of links. Clicking on the links will display the resource description.

1. The HTML:

We are going to need three elements for this:

  1. A text input for typing the search strings into:
    <label for="search">Search<input type="text/submit/hidden/button" name="search" id="search"/></label>
  2. A list to insert the search results into.
        <ol id="results"></ol>

    and:

  3. A div to display the resource descriptions in:
        <div id="description"></div>

2 The Javascript

At the command line, switch to the directory you saved your HTML file in, and do:

    svn co http://n2.talis.com/svn/playground/kwijibo/js/Talis.jQuery.plugin/trunk/ js/

Now we link to the javascript files from the bottom of the <body> of our html page:

<script type="text/javascript" charset="utf-8" src="js/jquery.js" mce_src="js/jquery.js"></script>
<script type="text/javascript" charset="utf-8" src="js/Talis.jQuery.js" mce_src="js/Talis.jQuery.js"></script>
<script type="text/javascript" charset="utf-8" src="js/jsRDF.jquery.js" mce_src="js/jsRDF.jquery.js"></script>

(jsRDF.jQuery.js is just a small, nascent library for manipulating RDF/JSON )

Now open another script tag, and we’ll write some javascript to connect our html with the platform:

First, we’ll declare some variables we’ll want to use:

var RSS_ITEM = 'http://purl.org/rss/1.0/item';
var RDF_TYPE = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
var MY_STORE = 'schema-cache';

For this tutorial, I’m using the schema-cache store, which contains many RDF and OWL vocabularies.

Now, what we want is to query the platform when we type in the text box, so:

$("#search").keyup(function(){
    var query = $("search").val();
    $.Talis.Store(MY_STORE).items(query, function(json){
        /*  we do something with the json data from the platform in here ... */
    });
});

What’s happening here, is we are taking the text that has been typed in the textbox (#search), and querying the items service of our store with it. The second parameter of the Store.items method is a callback function, in which you can specify what to do with the data when it is retrieved.

The platform items service returns the results in an RSS feed, which the jQuery.Talis plugin fetches for us in rdf/json, however, for this, we only want the items of the feed, not the RSS feed resource itself, so we need to filter in only the resources that have rss:Item as a value of their rdf:type property:

    var RDF = $.jsRDF(json);
    var rss_items = RDF.filter({p:RDF_TYPE, o:{value:RSS_ITEM}});

Here, we are loading the data into a jsRDF object, which has methods for manipulating it. We’re using the filter method to select the resources that have an rdf:type of rss:Item. Now we want to render them in the page inside our #results list:

$.each(rss_items, function(uri, properties){
    $("#results").append('<li><a href="'+uri+'" mce_href="'+uri+'">'+RDF.get_label(uri)+'</a></li>');
});

OK. We want clicking on those links to show the resource description, so we’ll define a function for retrieving that description from the store, and rendering it, then we’ll bind it the onclick event of the links in the results list:

function browse(uri){
    var uri = this.href;
    $.Talis.Store(MY_STORE).lcbd(uri, function(data){   

        var RDF = new $.jsRDF(data);
        $('#description').html( RDF.to_html(uri) );
        $('#description dd a').click(browse);
    });
    return false;
}

We get the URI of the resource from the @href attribute (which we set when we were rendering the search results), then we call the lcbd method on our store (LCBD is short for labelled concise bounded description, and returns the properties of the resource, and labels for all the resources our description references). Again, we use the $.jsRDF object to render the description as html (it uses a definition list for rendering the properties of the resource).

After we’ve rendered the description in the #description div, we also bind the click event on the links to the resource’s properties to the browse function, so that clicking on those links will retrieve and render the resources being linked to.

And that’s pretty much it.

Talis Store Plugin for ARC

The PHP coders amongst you may be interested in a Talis Store Plugin. To install it:

cd arc/plugins #yoru ARC plugins directory

svn co http://n2.talis.com/svn/playground/kwijibo/PHP/arc/plugins/trunk/talis/ talis
svn co http://n2.talis.com/svn/playground/kwijibo/PHP/arc/plugins/trunk/ARC2_SPARQLSerializerPlugin/ARC2_SPARQLSerializerPlugin.php ARC2_SPARQLSerializerPlugin.php

Then to use it:

require_once '../ARC2.php';   

/* configuration */
$talis_config = array(
  // 'db_user' => 'your_username',
  // 'db_pwd' => 'your_password',
  'store_name' => 'kwijibo-dev3', // your store name
   'fetch_graphs' => false, // If set to true, using FROM will fetch the graph as a datasource over the web, and store it in /meta
);
$store = ARC2::getComponent('Talis_StorePlugin', $talis_config);
$store->query("LOAD ")

What this does is let you use a Talis store instead of the ARC mysql store. It supports a subset of ARC’s SPARQL+ functionality. Specifically, it supports INSERT and DELETE (which I could translate to Changesets thanks to Benji’s SPARQL parser), but not the aggregate functions (which I don’t see a way to support in a client-layer at this point).

Some differences:

Named Graphs are currently a bit different in Talis stores - you can’t (yet) create your own on the fly as you can with ARC, so LOAD will put the data into the public graph by default.

Talis platform transforms bnodes into URIs, so .

I also added a few methods to the api:

$store->import($arc_store);
$store->export($arc_store);

(The idea is that you can move data between an ARC store and a Talis store).

I also added a $store->change($before_rdf, $after_rdf) method for submitting changes to an RDF graph.

It’s quite interesting comparing the two different ways of making changes (changesets and SPARQL+). I think that changesets (especially with the coming Batch Changeset support) are maybe a bit more amenable to programmatic resource updates from forms and the like. However, changesets are a bit verbose to hand-write for making quick edits and testing stuff, or pattern-based changes, and I’m finding SPARQL+ really handy for stuff like this.

What I’ve been thinking would be pretty neat would be if the SPARQL parser could be a bit more user extensible, and pre-query hooks could be set up (like ARC’s triggers, which happen post-query), so that plugin/hook writers could extend the SPARQL functionality, or just do stuff pre-query. Use cases might include:

  • rewriting SPARQL for performance improvement, or access control
  • pre-fetching data from FROM graphs over the web and adding it to the store (you can set a ‘fetch_graphs’=> true parameter in the config array you set up the talis store with, and it will do this)
  • adding versioned changesets to the ARC store
  • inventing new keywords - eg: ABOUT <http://example.org/foo> could be rewritten to DESCRIBE ?s WHERE {{ ?s rdf:subject <http://example.org/foo> } UNION {?s cs:subjectOfChange <http://example.org/foo> } } - Similarly you could add syntactic support for rollbacks, transactions, updates

You can see more usage examples at: http://n2.talis.com/svn/playground/kwijibo/PHP/arc/plugins/trunk/talis/Talis_StorePlugin.demo.php