SWP Tip: Organizing Queries and Views
SPARQL Web Pages is a flexible language to build web interfaces based on RDF data. Its flexibility makes it possible to apply different styles of development, depending on the size of the team and whether you are developing a quick demo or a maintainable system. In this post I examine some design patterns that I have found useful to keep my SWP projects well organized.
Let's walk through an example based on the infamous Kennedys ontology. You are welcome to follow along with TopBraid Composer 3.5 or above. In this example I am building a view that displays all children of a given Person in HTML:
The quickest way of building such a view is simply by attaching the following ui:instanceView to the Person class:
This approach has a couple of problems. Embedding the query into the document mixes presentation layer with application logic. This does not only make the page harder to read but also prevents division of label within a team of developers. Another problem is that nothing from the snippet above is easily reusable elsewhere. So let's start from scratch and do a clean design.
A key technology to separate layout from queries is to employ SPIN templates - named queries that can be stored in a different file and reused in many places. In TBC, we use the New > RDF/OWL/SPIN file wizard to produce a file kennedys.spin.ttl:
Note that you can make the file name identical to the domain ontology that it's for, but you should make sure that the base URI of that file is easily distinguished. I often add .spin to the end of the base URI. Checking the box that the "File will export SPIN Functions or Templates" will also give the file the .spin extension and register any contained templates globally in your workspace. Replace the namespace prefix from kennedys.spin to kenspin to make it a bit shorter.
In that new file, we add the domain model (kennedys.ttl) to the imports. Then we create a SPIN template that encapsulates the query to get the children. This template needs one argument: the Person to get the children of. In order to define arguments, SPIN includes the recommended namespace prefix "arg". Right click on sp:arg in the Properties tree and create a sub-property arg:person.
Then create a subclass of spin:SelectTemplates, called kenspin:GetChildren. Drag and drop the arg:person property from the Properties view onto the label spin:constraint on the form of that new class. This opens a dialog in which you can easily define the value type of the argument (kennedys:Person). Next, define the query as shown below:
The new SPIN template is now ready to be used elsewhere, also independently from SWP use cases. The SWP view definitions should go into a separate file. We create a new RDF/SWP (UISPIN) file with the following options:
Again, we can give it a similar namespace and file name as the domain ontology that it belongs to, but take care to keep base URI distinct and to shorten the prefix to something like kenui. In the new SWP file, we add the SPIN file from above to the imports. This will also import the Kennedys domain ontology.
Next we create a subclass of ui:Element, called kenui:ChildrenList. This is a new user-defined SWP view that can be used with its own (HTML) tag
The ui:prototype of this view is considerably shorter than the original starting point because it no longer contains the SPARQL query. Instead it uses ui:call to invoke the SPIN template that we had defined earlier. ui:call takes the name of the template as one argument, and all other arguments (such as arg:person) will be passed into the template. The result of the ui:call tag is that the variable ?rs will contain the SPARQL result set from the query. This result set is then used in a ui:forEach loop to walk through all rows, producing one HTML LI tag for each entry.
Putting this new SWP element into practice now is as simple as the following:
This pattern illustrates division of labor in web development teams: the HTML designer and the query expert only need to agree on a couple of names (the name of the template, the arguments and result variables), but apart from that they can do their own business independently. They work on different files - the SPIN logic goes into a .spin. file and the SWP layout goes into an .ui. file. The ontology itself is of course yet in another file and can be edited by a third group of people.