Thursday, November 10, 2005

The XForms Flickrbar and Flickr-strips

In my last post I showed a few screenshots of a browser toolbar that allows you to search Flickr. I also explained that the reason such a toolbar was very easy to build was because I was using both XForms and XBL. In this blog we'll look at the code used to create the bar.

Each image is a 'compound control'

The first piece of mark-up is the main form. There's nothing to it--we just need XForms input and output controls:

<html>
<head>...</head>
<body>
<xf:input ref="search">
<xf:label style="display: none;">Search:</xf:label>
</xf:input>

<xf:output ref="search" appearance="horzthumbnaillist">
<xf:label style="display: none;">Search:</xf:label>
</xf:output>
</body>
</html>
(The display: none; on the labels is simply so that assistive technologies can still make use of the text of the labels, but we actually don't want it rendered.)

At first sight it appears that this combination of controls doesn't do anything, but the set-up actually does an enormous amount. The first aspect is that whatever the user enters into the input control will also be present in the output control, because they both refer to the same node in the instance data:

<xf:input ref="search">
<xf:label style="display: none;">Search:</xf:label>
</xf:input>

<xf:output ref="search" appearance="flickr:horzthumbnaillist">
<xf:label style="display: none;">Search:</xf:label>
</xf:output>
The effect of this simple coupling is that the output control will receive notification every time the value in the node search changes. Since our framework will manage all of this for us via event notifications, we have created a very simple pipeline between our user's input, and what will ultimately be the Flickr servers.

The second thing of interest is that the output will render the list of images obtained from Flickr. Of course in ordinary XForms an xf:output will simply render the value of the node that it is bound to, but in our Flickr Topbar we're going to skin this control so that it renders a list of thumbnail images from Flickr that have been tagged with the word that the output 'contains'. (In other words, we not going to change the relationship between this input and output, we're simply going to change how the output is rendered.)

We can re-skin a control using many different mechanisms. So we might re-skin all triggers to be aqua buttons, or we might re-skin all modal messages to use a loud male voice. But in this example we are going to add something direclty to the form mark-up, and use the appearance attribute as our skinning 'hook':

<xf:output ref="search" appearance="flickr:horzthumbnaillist">
<xf:label style="display: none;">Search:</xf:label>
</xf:output>
From an XForms point of view this is fine. First, if an XForms processor does not support this particular value of appearance then it can ignore it and just render the underlying data as best it can. That may not be a lot of use here, but it shows that XForms has built-in fallback features, which in turn are possible because appearance is only intended as a 'hint' to the processor, rather than a mandated operation.

The second reason this is OK from an XForms point of view, is that since the value of appearance is a hint, then other processors could act in a different way. If you don't like my thumbnails strip, go do your own! (In fact you can replace my objects at any level down, including just the clock.)

We'll come to how the thumbnail stip iself is implemented in a moment, but before we do let's establish just how powerful this technique is. Now that we have a Flickr thumbnail strip completely encapsulated in a simple piece of declarative mark-up, we can re-use all over the place! For example, to show a set of images of hurricanes, we do this:

<xf:output value="'hurricane'" appearance="flickr:horzthumbnaillist">
<xf:label style="display: none;">Search:</xf:label>
</xf:output>
To show multiple Flickr-strips we need only do this:

<xf:output value="'hurricane'" appearance="flickr:horzthumbnaillist" />
<xf:output value="'tornado'" appearance="flickr:horzthumbnaillist" />
<xf:output value="'typhoon'" appearance="flickr:horzthumbnaillist" />
And of course, since this is still XForms, we can also use other controls like repeat, to get a whole bunch of Flickr-strips based on a dynamically changing list of tag values:

<xf:repeat nodeset="strips/strip">
<xf:output ref="." appearance="flickr:horzthumbnaillist">
<xf:label ref="." />
</xf:output>
</xf:repeat>
In this screenshot we have a Flickr-strip bound to some tags that have been retrieved from another web service:

Metabar showing metadata for a BBC news story

With this we have the power to creat as many Flickr-strips as we like, and they can relate to whatever terms we like. Now we're ready to look at how it's done.

XBL

The technique we use for implementing a Flickr-strip is to augment or decorate the output control with methods, properties, objects and event handlers, defined with XBL. The technique is a sort of cross between object inheritance and aspects.

Inheritance

It's a bit like inheritance because the output control functions like a base class, onto which other classes are layered. But it's more poweful than the inheritance you might be used to in Java and C++, since with those languages it's very difficult to add new classes at different points in the hierarchy. And it's certainly difficult to add new classes at run-time (although the decorator pattern goes some ways towards that).

Aspects

Aspect programming gets round this problem with inheritance by allowing particular key points of an application to be supplemented with additional code. For example, you might add some functionality that you want to be run at the beginning of a function before it's normal execution takes place, and some more functionality at the end, to occur after the normal execution has been performed. But the main problem with aspect programming is that the additional code is generally added at compile at time, and the extension points are usually pretty fixed.

Object Binding

The model we're using here is different to both of these; using some condition (in this case, the presence of an appearance attribute set to flickr:horzthumbnaillist) we add methods, properties, event handlers and other objects to the object in question. More than one set of these bindings can be added at a time, but quite importantly, the process is recursive--each of the objects added by the binding can itself have bindings.

The Source

Let's now walk through the source for the Flickr-strip bound object. The first part of the binding specifies further objects that will be added, indicated by the XBL content element:

<xbl:binding id="horzthumbnaillist">
<xbl:content>
The first thing we need to add to this object is an XForms submission that goes to Flickr and asks for a list of images that match a certain tag. This is easily done, as follows:

<xf:model id="m">
<xf:submission id="sub"
action="http://www.flickr.com/services/feeds/photos_public.gne"
method="get"
ref="instance('i-rq')"
replace="instance" instance="i-rs"
separator="&"
/>
<xf:instance id="i-rq">
<instanceData xmlns="">
<tags>*</tags>
<format>rss_200_enc</format>
</instanceData>
</xf:instance>
<xf:instance id="i-rs">
<dummy xmlns="" />
</xf:instance>
<xf:action ev:event="ev-find-images">
<xf:send submission="sub" />
</xf:action>
</xf:model>
In this structure, when the submission is invoked it will take the URL in action and combine it with the data referred to by ref, in this case the instance i-rq. The parameters to Flickr (in the i-rq) are the tag you are looking for, and the format of the result set--in this case RSS 2.0--these results being placed in the instance i-rs.

Once we have the results, they need to be rendered, and we do that with a simple XForms repeat:

<xf:repeat model="m" nodeset="instance('i-rs')/channel/item">
<xf:output ref="." appearance="flickr:thumbnail" />
</xf:repeat>
</content>
This simply iterates each RSS item, and then renders it with an output, and as before, the output is bound to some other object, in this case a flickr:thumbnail object.

All that remains is to fire this request to Flickr, which we do when the XForms model notifies us that the data has changed. (Recall that all of this is sitting inside an output wired up to the search node in the instance data.) The first point is that each control must support a method called setValue, which is called inside an event handler, and this method will receive one parameter which is the new value of the data:

<xbl:implementation>
<xbl:method name="setValue">
<xbl:parameter name="newVal" />
The actual function itself is written in script inside an XBL body element, and the first thing we do is check for a change in the value:

<xbl:body>
// <![CDATA[
if (newVal && newVal != '')
{
Next we go and find the XForms model and the instance that contains the search criteria, and set the tags element to the current value of the output that contains us:

var m = this.all.tags("model")[0];
var i = m.all.tags("instance")[0];
var pDOM = m.getInstanceDocument(i.id);
var oTags = pDOM.selectSingleNode("//tags");

oTags.firstChild.nodeValue = newVal;
Finally we tell our local, nested model to run the submission:

var oEvent = this.ownerDocument.createEvent("Event");

oEvent.initEvent("ev-find-images", false, false);
m.dispatchEvent(oEvent);
}
// ]]>
</xbl:body>
</xbl:method>
</xbl:implementation>
</xbl:binding>
To summarise, there are three key parts to what we have just done. The first is that we've used the ordinary notifications that the XForms processor gives us when data is updated as our prompt to go get some data from Flickr. This is a powerful technique, because we're not having to do any monitoring of particular data, and the interface between the event and the source data is standardised.

The second thing we do is to encode the request to Fickr in an XForms submission, which keeps it nicely encapsulated; if we want to change the service we are referring to it's easily done.

These two things effectively define the interface between our object and the outside world--on one side from the data part of the host XForm, and on the other side the interaction with Flickr. The remaining part is that the results are rendered with very simple outputs, but with an indication that we want each item rendered as a thumbnail:

<xf:repeat model="m" nodeset="instance('i-rs')/channel/item">
<xf:output ref="." appearance="flickr:thumbnail" />
</xf:repeat>
</content>

The fact that the Flickr-strip is an object that is in turn made up a set of thumbnails gives our model incredible flexibility. The next step is to look at how the thumbnail is defined.

A Flickr Thumbnail

The thumbnail is very easy to create, and is simpler than the Flickr-strip since it doesn't need to do any submitting of data. Also, since it merely maps to a couple of further controls, it doesn't need to respond directly to any events.

The first thing we do is create a span of a fixed size, so that we can ensure a neat layout:

<xbl:binding id="thumbnail">
<xbl:content>
<span style="width: 83px; height: 95px; padding-right: 5px;">
Within this span we going to create a sort of 'canvas' onto which to render first the Flickr thumbnail, and then the time that the photo was taken, and we'll use ordinary CSS positioning to place this on top of the image. First the canvas:

<div style="position: relative; top: 0; left: 0; height: 78px;">
Now the Flickr thumnail--and note two things; first, that we are using the XForms mediatype feature to render the image from the URL. And second, that since the image is still a plain ordinary XForms output there is nothing to stop us from using hint to show the description of the image, stored in Flickr:

<span style="position: absolute; top: 0; left: 0;">
<xf:output
ref="media:thumbnail/@url"
mediatype="image/*"
style="border: 1px solid black; padding: 0; margin: 0;"
>
<xf:hint>
<xf:output ref="../../media:text" />
</xf:hint>
</xf:output>
</span>
Having rendered the image, we now position in the top right-hand corner of the thumbnail the time that the photo was taken:

<span style="position: absolute; top: -10px; right: -10px;">
<xf:output
value="inline:gettime(string(pubDate))"
appearance="fp:analogue-clock"
class="flickr-clock"
/>
</span>
</div>
You'll have noticed that this is also 'skinned', this time with a binding that implements an analogue-clock. In much the same way as with the Flickr-strip, whose input was a simple string for a metadata 'tag', here the 'input' is again a simple string, but this time a value indicated using the 24-hour clock. (And as before, since appearance is a hint, if a processor doesn't support analogue clocks, then this will just render as text.)

The final bit of our thumbnail is the actual title of the image. We use CSS to ensure that the text of the title doesn't make our thumbnail too wide:

<xf:output ref="title"
style="width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;"
/>
</xbl:span>
</xbl:content>
</xbl:binding>

The Clock

We won't recurse down to the next level, which is the analogue clock, but it's worth pointing out that the clock is implemented in SVG, and is the same clock that is used in other examples distributed with Sidewinder from the formsPlayer site. One thing worth drawing attention to though, is that the size of the clock is set using CSS in the main form:

xf|output.flickr-clock
{
width : 30px;
height : 30px;
}
The use of CSS to specify the behaviour of dynamic widgets is incredibly powerful. Although the embedded widget was implemented with SVG, it was created so that it would use the CSS form its containing object, so all an author has to do to control the size of the clock is set the size of the element that the clock is bound to. So to increase the size of the clock when the user moves their mouse it, all we need to do is the following:

xf|output.flickr-clock:hover
{
width : 60px;
height : 60px;
position : relative;
right : -15px;
top : -15px;
}
Here we simply double the size of the clock, and change its position slightly so that it remains centred:

Controlling the Widget

Conclusion

The use of declarative mark-up languages such as XForms is becoming established as a powerful way to build sturdy, testable and accessible programs. However, when coupled with XBL, both object management and reuse become even more efficient and powerful. When objects created through this mechanism are given the power to communicate with external data sources, as we saw here with the Flickr-strip, then a technology becomes available to us that can leverage the power of todays decentralised web, but in a way that does not require enormous skills and resources.

Unlike the 'mash-up' approach where servers are used to combine different data sources together in interesting ways, the approach described here puts client software in control (or to be more precise, the user at the centre of the web), and crucially, defines clear and simple interfaces between one set of data and the next.

A new generation of web applications is made possible by this combination of technologies.



Tags: | | | | | | | | | |

Sunday, November 06, 2005

Platform 2.0

It certainly feels nowadays like everything needs a "2.0" on the end before anyone will take it seriously. Which means that our new platform for internet applications can't just be a new platform it has to be Platform 2.0.

We've come a long way in building a new platform that makes it very easy to build internet applications with a hefty dose of the Semantic Web, and as a taste of what is to come, we've done some work putting some of this new platform (I mean, Platform 2.0) into current browsers via extension bars. We've actually created two simple bars; one is a toolbar that allows you to search Flickr, the other is a side-bar that shows metadata about the site that you are looking at:

Metabar and Flickr Topbar

It is difficult to describe just how easy these bars are to build using a new...er, sorry...Platform 2.0. But take a look at the screenshots, and note how data is skinned so that it is presented how the user wants it to be. For example, in the Metabar geo postioning data in the document you are viewing is rendered as a map. And if the site you are looking at is a blog then the Technorati details of the author is shown.

And perhaps most exciting, skinning the data is recursive; the Flickr Topbar is just one widget, made up several other widgets, and the top-level widget is driven by a tag. So all you have to do is pass a word to this 'Flickr widget' (or rather 're-skin' the word itself) and it will render as a list of images retrieved from Flickr. But each image is itself another control, made up of a small SVG clock superimposed over the image to show the time the photo was taken. And the clock is itself a further control...moving the mouse over the image makes it grow, to make it easier to read, and it could easily be replaced with a digital clock, for example:

Controlling the Widget

But the power of Platform 2.0 (hey, it's growing on me) is that this 'Flickr widget' only needs a word or two as input, to then show an image strip. Hop over to the Metabar and you will see that the same widget is showing Flickr images that are on the same theme as the document you are reading. This is done by taking the page's 'description' metadata, feeding it to a Yahoo! service that converts it to a set of metadata tags, and then feeding each tag into one of our handy little Flickr strips:

Metabar showing metadata for a BBC news story

This is what the geekarati call a 'mash-up', but the problem with mash-ups is that they invariably show the talent and tenacity of the programmer, and what Platform 2.0 is concerned with is making it just as easy for the user. If the user wants to feed their meta tags into Flickr and get some pictures whilst they are browsing, then that's easy. And if they want to use Alexa, or del.icio.us or Yahoo! to get those tags, then that's easy too.

I would say Platform 2.0 warrants going up a version number because for the first time it puts the user at the centre of the web. This really is your web, the way you want it--no subscribing to other people's servers, or waiting for someone to produce exactly the mash-up that you want.

And then who knows--maybe we'll really get Web 2.0.


Tags: | | | | | | | | | | |

Sunday, October 23, 2005

CURIEs: A Compact URI Syntax / Semantic Links

It's increasingly common to see software using QNames to abbreviate URIs. But strictly speaking, QNames cannot represent all possible URIs since they were devised only to name XML elements. I recently proposed 'CURIEs' as a solution to this.

Introduction

If you use Wiki software or RDF, you'll be very familiar with using QNames to represent a full URL. For example, many Wikis support a feature where a prefix like isbn can be substituted for something like:

http://www.amazon.com/?isbn=
or:

http://www.barnesandnoble.com/?q=
When a Wiki author wants to make use of the substitution, they simply type into their posting they would use syntax similar to this:

Go and buy T. V. Raman's [[isbn:0321154991][book on XForms]].
and the Wiki software will automatically generate:

Go and buy T. V. Raman's
<a href="http://www.amazon.com/?isbn=0321154991">book
on XForms</a>.

The Problem

The problem is that isbn:0321154991 is not a valid QName. The reason for this is simply that QNames were originally devised to provide a way of scoping XML element names with namespaces, and an element name cannot begin with a number.

Another example--and indeed the one that kicked off the whole thing when I was doing some metadata consultancy--involves the IPTC subject codes. The IPTC's taxonomy has a set of subject codes for news articles; to pick an example, the code 15002000 represents alpine skiing. The IPTC would like to be able to represent these codes in a convenient form in their documents, in such a way that they are not only compact, but it's also easy for news organisations to add their own codes. The obvious choice was to use QNames for this, since they allow different organisations to adopt their own namespaces to qualify the values. But as with our ISBN example, iptc:15002000 is not a valid QName.

Why these examples are not valid should become a little clearer if we look at the background to QNames. In ordinary XML (pre-namespaces) the following are all valid element names:

abcd
ab:de
ab::::cd:efg:h
They are valid because the colon is just another legitimate element name character. When namespaces were added to XML the authors were looking for a way to split a name up, and decided that the colon should be used to do this. These new element names--with a 'context' to precede the element name--were called 'qualified names', and the mechanism for 'expanding' them is simply to take the namespace represented by the part before the colon, and then append to it the part after the colon.

This is probably all easy-peasy stuff to you, but here is an example anyway; an element name like xforms:input translates to be the input element, but within the namespace defined by the prefix xforms.

The 'common convention' that has arisen is that this same syntax can be used to pass around a URI. So for example, if in RDF I want to use the Dublin Core creator property, then all I need do is this:

dc:creator
and provided that I have the dc namespace prefix defined as http://purl.org/dc/elements/1.1/, I have effectively represented the following URI:

http://purl.org/dc/elements/1.1/creator
To recap, what we have done is used a technique that was devised specifically to scope XML elements, like this:

<dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">
...
</dc:creator>
to represent a URI--in this case, this:

http://purl.org/dc/elements/1.1/creator
But as we've already observed, you cannot represent all possible URIs with QNames.

The Solution

We can resolve this problem pretty simply, by inventing a new datatype which allows the part after the colon to be anything. That's exactly what I have done with my Compact URI syntax (abbreviated to CURIE), making all of the following examples acceptable:

home:#start
joseki:
google:xforms or 'xml forms'
:#start
:
:xforms or 'xml forms'
Note that any valid QName remains a valid CURIE, but of course not all valid CURIEs are valid QNames.

RDF/A, CURIEs and URIs

This is all pretty straightforward, and as I mentioned before, in relation to software like Wikis this is merely a codification of existing practice (I'm not saying that's a bad thing).

However, it all gets a little trickier when you put CURIEs into their intended context, which is a new syntax for RDF called RDF/A. I'll discuss it in another blog, but I'll just mention it now because a new draft has been produced, as part of the ongoing process of incorporating RDF/A into XHTML 2. (A number of smart people from the RDF in XHTML Taskforce have been contributing to the thinking, and as part of this process of incorporation.)

Anyway, as a brief overview, the main idea of RDF/A is to allow XML documents to 'carry' their own metadata. There are many situations where you don't really need a separate document to carry your RDF/XML, since the main document carries much of the same data. This often happens with clumps of metadata like FoaF, but also often happens with RSS.

But whilst RDF often makes good use of QNames (and so too, RDF/A makes use of CURIEs), unfortunately when you move back to the XHTML side, you have to spell everything out as full URIs in your links. (One of the goals of RDF/A is, as Ben Adida memorably put it, to "bridge the Semantic and clickable webs".) So RDF/A allows the use of CURIEs to express ordinary inline links, but allows a processor to differentiate a CURIE from a URI by using square brackets:

<div about="">
This document is licensed under a
<a rel="[cc:license]" href="[lic:by-sa/2.0/]">
Creative Commons License
</a>
which, among other things, requires that you provide
attribution to the author,
<a rel="[dc:creator]" href="http://ben.adida.net">Ben Adida</a>.
</div>
This chunk of XHTML will generate the following triples:

<> cc:license
<> dc:creator
As I discuss in the document, this is the part that I feel is most exciting about CURIEs, since now it means that navigable links can themselves be passed semantically. More on this and our work on a 'semantic web browser', in a future blog.


Tags: | | | | | | | | | |

Friday, September 23, 2005

XForms: An Executable Pattern Language

XForms is an exciting new technology, not just because it removes a whole load of spaghetti script, but because it deals primarily with patterns rather than code.

Introduction

I realised when I saw a recent blog of Bill McCoy's (which is a reply to my blog, but which is itself a reply to his blog, which was in its turn a comment on my blog...Yes, it has often occurred to me that there might be no-one out there reading this exchange other than me and Bill) that the discussion about XForms and declarative programming might end up being just a debate about whether using XForms is better than using script.

Of course that's part of the discussion, but it's certainly not the whole story. The problem is though, that many of the things I've discussed in relation to XForms patterns have tended to also look at AJAX and scripting (since that is often the only place where you can find something to compare with) and I think I have probably given the impression that my prime concern is script.

AJAX and xf:submission

Take for example my discussion about how the standard AJAX HTTP submission mechanism works (yes, with no page refresh...I know, I know...and what will we get in 10 years time when AJAX 2 comes out?).

Recall that the most common way of doing an AJAX request is to set up script like this:

var req;

function loadXMLDoc(url) {
// native XMLHttpRequest object
if (window.XMLHttpRequest)
{
req = new XMLHttpRequest();
req.onreadystatechange = readyStateChange;
// IE/Windows ActiveX version
} else if (window.ActiveXObject)
req = new ActiveXObject("Microsoft.XMLHTTP");

if (req)
{
req.onreadystatechange = readyStateChange;
req.open("GET", url, true);
req.send();
}
}

function readyStateChange() {
// '4' means document "loaded"
if (req.readyState == 4)
{
// 200 means "OK"
if (req.status == 200)
{
// do something here
} else
{
// error processing here
}
}
}

(Although a more complete approach would look to handle the error conditions.)

Now the point is not that this is 'wrong', or even inefficient. But simply that in the same way that I eventually got bored of writing optimised assembler algorithms to do multiplication (and started using C instead), so today I really can't be bothered to have to set up code such as this to do nothing more than provide a line of communication with a server.

Of course some will reply that there are already many AJAX libraries emerging that will allow you to do this using some simple APIs, hence hiding this kind of code. But putting aside the fact that we don't have a standard for them, using classes and an API means we're still reserving these useful techniques for the most experienced programmers.

Anyway, let's map this code to XForms:

<xf:submission
id="sub"
method="get"
action="http://example.com/customers"
/>

Pretty simple...but I was using this as an illustration of how the advantages of XForms are not just that it is easier than scripting, so let's dig a little deeper into what XForms submission offers.

The Submission Pattern

As I said, it looks like what I'm saying is that XForms is better than script. I have to say that if that were all we'd achieved with XForms then I'd be pleased, but a lot less vocal. XForms has actually provided us with something far more significant--we now have something close to a pattern language, but one that thinks it's a programming language.

To show you what I mean, let's think of our submission as a pattern. What we've got is some behaviour that is defined in a pretty abstract way, along the following lines:
'get' some data from one URL, or 'put' some data to another URL, and when done, generate either a 'success' event or a 'fail' event.

The strength of any pattern is in the fine balance between being sufficiently general that it can apply to many situations, but not so general that it says nothing. In this case it does seem quite vague--getting a document from here and putting it there--but when you think about it, that pretty much covers most of the basics when it comes to sending an email, saving a file to disk, retrieving an RSS feed, posting a document to a server, and so on. It certainly captures our AJAX request.

So, if this is a pattern language that thinks it's a programming language let's see then how XForms uses this pattern to get a file from your disk:

<xf:submission
id="sub"
method="get"
action="file:my-data.xml"
/>

Mmm. So no new API is needed to make the shift from HTTP to the file system? Are we really saying that any author/programmer who mastered the most common technique--the one that gets or puts an XML document to or from an HTTP server--has therefore got teh complete skill-set for getting and putting the same document to or from the hard-drive?

The answer is of course yes, but let's go further and see what new skills our author needs to acquire to send the same XML document by email. Surely they'll need to buy a book on MAPI:

<xf:submission
id="sub"
method="put"
action="mailto:john.doe@example.com?subject=Results"
/>

No new API again? No need to roll your sleeves up and learn MAPI in order to write a powerful application that will allow a user to enter some XML, validate it, and then send it via email?

And that is the key point; it's not that we've hidden a whole load of script--which of course it goes without saying that we have--but rather that we've devised a simple language that captures an enormous amount of generic functionality, whilst crucially still allowing us to use that functionality in very specific situations. We get our specific functionality without learning lots of specific APIs. (And I haven't even mentioned that this simple pattern captures even more functionality; as well as automatically validating the data before it sends it, it also provides an option to serialise the data in a number of different formats.)

Databases

One final example of the power of this approach comes in the form of an enhancement that we added to formsPlayer 2, which allows databases to be accessed using this same pattern. At first sight it seems that our Submission pattern couldn't be appropriate for databases, but if you consider that a SELECT query is like a 'get' and modifying or inserting a record is like a 'put', then we find that our pattern works for us once again.

Since the submission pattern involves the use of an XML document and a URL, then the trick is to convert the XML data to and from relational tables, and to make use of the URI syntax to work out what table is being accessed.

But none of this is that difficult, and there are many ways it could be done. In our implementation we chose to make the URI into a combination of a full ADO string (to select the database) followed by the name of the table to access. So to obtain a full list of the contacts (as an XML instance) that are stored in the tContacts table, we just do this:

<xf:submission
id="sub-get-contact-list"
separator="&amp;"
method="get"
action="db://Driver=\{Microsoft Access Driver (*.mdb)\};Dbq=contacts.mdb;/tContacts/contact"
replace="instance" instance="inst-contact-list"
/>

Note that the use of '\{' and '\}' is because in formsPlayer 2 you can use Attribute Value Templates to specify the URI. Also, since this is full ADO you can access many other data sources, from MySQL and SQL Server databases, to Excel spreadsheets and CSV files.

To update a row in the table (i.e., save any changes) we do this:

<xf:submission
id="sub-put-current-contact"
bind="ns-current-contact"
action="db://Driver=\{Microsoft Access Driver (*.mdb)\};Dbq=contacts.mdb;/tContacts/contact"
separator="&amp;" method="put"
replace="none"
/>

The contacts application that comes as part of the Sidewinder install makes full use of this technique:


Contacts database viewed through the Sidewinder Viewer Posted by Hello

Conclusion

Of course in all of these examples we have replaced some script--although in each of these cases the scripts we have replaced will be extremely different to each other--but far more importantly we have created a pattern that has sufficient flexibility to be continually applied to new situations. And in this case, when applied to databases, our pattern even stands up pretty well to very specific, purpose-built approaches like LINQ. (See also Visual Basic 9.0: Looking Forward
by Scott Swigart.)



Tags: | | | | |

Sunday, September 11, 2005

Using Google Suggest to Categorise del.icio.us Links


Using Google Suggest to Categorise del.icio.us Links Posted by Picasa

I promised when I posted the XForms side-bar to add del.icio.us links that I would add some new features. The first one--which I've been pondering for a while--is how to improve the process of tagging the links that you add.

Anyone who has used del.icio.us will know that it does a pretty impressive job of giving you a list of all the tags that you have used before, as well as making it very easy for you to add and remove keywords for a particular link. But the problem with it is that more often that not you want to see the tags that other people have used, not just your own. After all, we're talking about social bookmarking, so if I want to add my links on a particular subject to the links on the same subject that are already there, then I have to be using the same tag as everyone else.

As it happens, we're really making the best of a bad job anyway. Despite what fans of so-called microformats and folksonomies say, it is not possible to effectively tag a document or link with unqualifed words. You might get away with it amongst very small groups of people with a specific shared interest, but the moment you go slightly wider the ambiguity brings the whole thing crumbling down. Technorati, for example, make use of exactly this technique, but already there are problems where the same word has been tagged multiple times, for example London Bomb, London Bombings and London Explosions. (Supporters tend to suggest that we don't need the big solutions--hence 'micro'--and we don't need any standards organisations telling us what words to use--hence 'folks'--but no-one quite says how we avoid ambiguity or this kind of duplication. I hope to return to all of this at some point, and at the same time hopefully show why I came up with RDF/A.)

Still, although we may not have a 'proper' metadata solution, del.icio.us and other similar systems remain pretty handy. (See Adam Mathes on Folksonomies - Cooperative Classification and Communication Through Shared Metadata on why folksonomies are still useful.) So I figured that if there was a way for us all to choose from a known lists of words then although it's not a full metadata solution, it might at least be possible to establish a reasonable level of common ground. But to really make it work, it seemed to me that people would need to be able to choose their own lists; a bunch of XMLers might choose a list from XML.com to get their tags from, whilst literary theorists, chefs and cricket fans might choose others.

I decided therefore to incorporate my XForms version of Google Suggest into my XForms del.icio.us link manager (yes, there does seem to be a pattern emerging, doesn't there!). However, unlike the functionality provided by Google Suggest, which makes use of embedded script, my "XForms Suggest" can easily be changed to point to any source of XML data. The source of data I had hoped to use was DMOZ, but unfortunately, I can't find a web service that allows me to search DMOZ and get back XML. (If anyone knows of a server that has the DMOZ directory on it and that returns XML then please drop me a line. Otherwise we may just do it ourselves.) In the meantime, for a proof of concept I have used Google Suggest again, which as it happens is not a bad source of tags, since the words in the list are the words that people are using to search Google for...so why not use them to tag our documents, too?

The XForms code itself is very simple, but the main enhancement over the previous code is to use a repeat to hold the suggestions, and to place it inside a switch/case construct. Then whenever the user enters the input control to get a suggestion, the list of suggestions is toggled to be accessible, and when the control loses focus the list is toggled away. The repeat itself contains a list of triggers with the suggestions as their labels; when the user activates one of them the selection is added to the list of tags for the link.

A recent blog by Eric Barroca suggested that AJAX does not compete with XForms !, and that they could co-exist. I know what Eric is getting at, but examples like "XForms Suggest" shows that they don't compete because AJAX is just no competition, since our XForms can be easily changed to use any source of XML data for the list of suggestions, and yet is coded in a sufficiently abstract way that it will run on both a GUI and a voice system.

If you fancy giving this little application a whirl then you should make sure you have version 1.3.5 of formsPlayer from the download area of our site.

Once you have the new version, simply go to the configuration form. This is just an XForm, and it doesn't need to copy anything from our server--i.e., it doesn't do any component installation, since bar installation just involves calling some built in XPath functions in formsPlayer. After successful installation you will need to open a new browser, and then you will have an option formsPlayer Bookmark Manager in the Explorer Bar menu, under the View menu of IE.

(Note that if you followed these steps to get the first version of the link manager, then you don't need to do anything; the XForms is on our server and so you will be using the new version next time you open the pane.)

The buttons on the form are pretty straightforward; you can save your link and metadata or cancel. Use the refresh button to reload the title and metadata from the page currently in the browser. To get suggestions, navigate to the Get Suggestions control and start typing--suggestions will appear just below the control, and you can either select one with your mouse, or press [ENTER] to choose the first one in the list. (There is a problem in that sometimes Google uses &nbsp; in the returned data, and since this is not defined the suggestion results won't load. Just carry on typing and you will normally get past it.)



Tags: | | | | | | | | | | |

Sunday, September 04, 2005

On Adobe and XForms via Declarative Programming, Wizards and Aspects

My previous blog about building RESTful applications with XForms (A del.icio.us Link Manager Written in XForms) has prompted a reply from Bill McCoy at Adobe. Bill is responsible for platform product management, which includes the desktop and mobile versions of Adobe Reader, and the associated PDF technologies. By all accounts he has good reason to be interested in the 'next generation' of internet applications.

The main point of his blog is that the declarative approach to building internet applications that I have been championing is:
still a bit of a Holy Grail: a rich application may be able to be built script-free but while I'm a bit astonished at what Mark has shown can be accomplished within XForms, at some point the complexity of the XML markup arguably exceeds what a script-based approach would have produced.

Flattered as I am that Bill is impressed--and the good news is that we have plenty more applications to be released that are even better than the ones currently available--I have to disagree with this view that the complexity of XForms applications increases until "at some point", scripting works out better. I'll look at this, as well as the more substantial point of Bill's blog, that the declarative approach itself is a problem, and actually not as useful to programmers as better code-generation tools.

Complexity

The particular example of "complexity of the XML markup" to which Bill is referring is in the RSS Reader application that I built using XForms. (This application is provided automatically when you install formsPlayer, but the source is available as a text file.) The main thing that he is honing in on to illustrate this 'complexity' is that in order to create a looping construct I was forced to use a workaround. Since XForms does not yet support loops, I used an XForms action that deletes a node, and then used the notification event that deleting a node generates, to delete the next node. In effect we get a while loop that lasts as long as there are any more nodes to delete--but as Bill rightly points out, it's rather an odd way to get a loop!

It should be said firstly that the main reason for doing this is to convert the data read from the many different types of RSS feed that are available into a common format for storage, in this case XHTML 2. If I had just stored the feeds 'as is' then no loop would be necessary, but one of the things that I wanted to illustrate with the application was how XHTML 2 will increasingly become the 'universal document'.

And it should also be added that I was trying to show how the whole thing could be done using XForms 'out of the box', with no proprietary extensions. As more and more XForms processors emerge and head towards the full implementation of XForms, then my RSS Reader should work with them, regardless of whether the target processor is geared up for speech, SVG, XHTML and so on.

Those Slow Standards-bodies

But more importantly, if this is the only criticism we have of XForms' complexity, then I'm pretty pleased. Let's be honest, adding a looping feature to XForms (or XML Events) would take no time at all, and once it has been added I could then remove the workaround.

(And as it happens, David Landwehr from Novell has already proposed a set of extensions to XForms, such as if and while, and he has even implemented them in his processor. Bill's criticism is therefore largely about the lumbering process of creating and updating standards, and not the architecture of the language. That is still a legitimate criticism, and one with which I concur strongly.)

Streamlined Scripting?

But putting aside the complexity of my workaround, I seriously doubt Bill's claim that a script version of an RSS reader would be less complex than the XForms I have produced. Looking at the scripts for internet applications such as Google Maps, GMail, Microsoft's Virtual Earth, and so on, they are incredibly complex, and require pretty large teams to both build and maintain. And the reality is that so far, RSS readers aren't written using script anyway1--they're built with C++, Java or VB. Which therefore makes it all the more impressive that an XForms RSS Reader can go toe-to-toe with applications built with such serious programming languages.

Wizards

Bill's more substantial point is that maybe what the world needs is not some new declarative programming paradigm at all, but better tools for generating procedural code. He gives the example of Ruby on Rails, which is an environment that automatically generates the large numbers of files needed to build typical web applications that are based around a database. The framework makes it easy to build a RESTful application which could add and delete customers, for example, handling the automatic generation of a UI, the generation of SQL queries to manipulate the data, and so on.

But a sub-text of everything I have been tring to illustrate in my blogs and XForms-based applications is that the wizard part is easy if the underlying architecture is right. That's why I frequently try to show that you can build powerful applications using simple text editors, since after that it's a no-brainer to build a tool that generates the right XML.

And one of the main reasons I have taken this approach is that in nearly all cases I find the 'wizard approach' is great to get you started, but then very quickly gets complex again. Anyone who uses Microsoft's Visual Studio, for example, will know that getting a C++ application up and running quickly, with support for multiple windows, toolbars, printing and file saving, is a snip. But then when you want to modify that code and move away from the wizard, you are very soon into normal C++ territory.

That's fine if you are a C++ programmer, and your employer has time to wait and budget to use up. But if all you wanted to do was produce, I don't know, let's say...an RSS reader as a side-bar in Internet Explorer, then it's a lot of work for what should really be a simple application2.

In many ways Ruby on Rails follows the same lines as the Visual Studio wizards; you can generate a large number of files for one of the standard application types, which gets you off your starting-block pretty quick. And if you enhance that application along established lines, your productivity can remain quite high. But stray too far, and soon you will again be on your own, in the world of templates and the rather obtuse Ruby programming language3.

So no matter how good a wizard might be, the real question is how productive will you be in the underlying language, once you have moved beyond the capabilities of the wizard.

But even this is not the whole story. Although I feel that XForms can hold its own as a language that can be used in a very wide range of applications (with obvious room for improvement), the key to my approach to internet applications is in the way in which code can be re-used.

Re-use

What I have been championing for the last few years is not XForms as the solution to everything, but XForms as a component of a much wider solution. This point is important, since focusing solely on my support for XForms has led Bill (and others4) to suggest that I am over-egging the pudding:
It seems to me that if declarative model-based approaches to application construction are going to take off, advocates need to change the rules, and stop trying to oversell programmers and scripters on non-programmatic approaches.

I have never claimed that XForms is a "non-programmatic approach"--far from it. What I have said though, is that just as more programmers can use C than assembler, and more programmers can use Visual Basic than Java, so I believe that a programming model based around events, declarative mark-up, a spreadsheet-like dependency engine, automatic reflection of model state to the UI, automatic validation using standards, easy encapsulation of data submission, and so on, is easier than scripting, AJAX, C++, VB, Java, and yes, even Ruby on Rails. And that has to lower the bar.

And the most important features of the 'approach' that I am trying to "oversell programmers and scripters on", concern (a) the dynamic extension of objects at run-time, and (b) a declarative virtual machine. I'll be writing more on this shortly, and it will also be the subject of my comments on a round-table at SD Best Practices (XForms, Web Forms, or What? The Next Generation of Rich User Interfaces, with Elliotte Rusty Harold, Stefano Mazzocchi, and Luis Derechin), but for now I'll just touch on a couple of things:

  • the dynamic extension of objects builds on XBL to allow objects to be 'decorated' at run-time to provide functionality that simply cannot be achieved with traditional class inheritance. The approach I'm taking is not unlike aspect programming but it happens at run-time, and of couse unlike the usual way of doing aspects, the definition of the cross-cutting concerns is itself declarative;

  • the declarative virtual machine is something that I have outlined in the past, but it allows complex functionality to be built up from other declarative components in a simple modular way, such that not only is development and testing quicker, but even specifying standards is faster. It's more akin to an XML pattern language.

I'm hoping to look at these issues a little more on this blog, in the lead up to the SD Best Practices conference, but to re-cap this discussion; Bill suggests that my approach to XForms evangelising is to make wild claims for declarative programming, before suggesting that what we really need are better tools. My response is that any bold claims I do make are for a whole new approach to developing applications, of which XForms is only a part...albeit a crucial one.

Applications that Build Applications

However, none of what I have said above would cause me to disagree with Bill's closing comments:
Instead we should create new classes of tools that really are for non-programmers, that do things like hide the complexities of XML Schema and XPath. When the day comes that non-programming users are really building production-level RIAs, I'll wager long odds that they won't be doing so by editing XML XPath node-set expressions in Notepad.
Of course, like all good bookmakers, Bill won't be losing any money on a prediction like that (although he may not find too many punters prepared to hand over cash either). But whilst I too want to see exactly this revolution in application development, I feel that it is not about to happen any time soon because the languages being used to try and write such applications are still rooted deeply in the procedural past.

In fact, the reason I leapt on XForms about three years ago, was because at the time I was actually trying to build UIs that were based on RDF schema, but was finding it painful to build the necessarily dynamic UIs--if I used HTML it was too underspecified, and if I used C++ or Java you just spent too much time adding new features.

But the combination of XForms, XHTML 2, SVG and XBL does provide a platform which could be used to build the next generation of applications and as Bill wants, the next generation of application-builders. Of course, whether that happens sooner rather than later will depend on the people who are currently trying to offer ever more sophisticated internet applications; it will depend on whether companies like Yahoo!, MSN and Google continue to give developers old-style APIs--as Google Maps has done--or whether they adopt a new approach for the new generation of RIAs and RIA-builders.



Tags

| | | | | | | | | | | |

Notes:

1: I did find a simple 100-line script, but it only shows one feed, and the URI for that feed must be specified in an input box. The XForms RSS Reader takes about 450 lines of XHTML and XForms (plus some additional CSS), and allows the saving of a number of feeds with all of their details and current values--in other words a pretty much full-featured reader.

2: It's interesting that Microsoft have also decided that RSS readers shouldn't be so difficult to write. They are building into Vista a component that will track feeds and place the data into some sort of store which can then be retrieved by various viewers and applications.

3: As it happens Ruby on Rails works quite well with XForms. I'll try to find time to show a demonstration of this in action.

4: And just in case anyone missed Bill's point, Rob McDougall follows it up with a 'comment' on the blog:
As you [Bill] point out, it's common for advocates of declarative grammars with specific targets to oversell the general usefulness of their solutions.

I don't know how "common" it is for anyone to advocate a declarative approach. Most of the blogosphere is taken up with dicsussion of AJAX and Ruby on Rails which are far more trendy, and their advocates wouldn't touch a declarative model with a barge-pole. So you may accuse me of "overselling", but I don't see it being "common". (Although T. V. Raman, formally of IBM and now of Google, may protest that he is 'overselling' declarative mark-up just as much as me.)

Saturday, August 06, 2005

A del.icio.us Link Manager Written in XForms


Side-bar for IE to add links to del.icio.us. (Built using formsPlayer and XForms.) Posted by Picasa

Sorry it's been a bit quiet on the blog front, but things have been very busy here. The good news is that IBM's active promotion of XForms seems to be generating wider interest in this technology. But the bad news is that it seems to have panicked one or two server framework companies into claiming support for XForms when they patently don't have it. I'll be looking into some of these things in a future blog, but for now it might be worth saying...don't worry! Anyone worried about missing the XForms boat, there is still plenty of time to get it right. (And perhaps I should look on the bright side--when people start claiming to support a technology when they don't, it just might mean that the technology in question is coming of age.)

Anyway, on to the subject of this blog. I've been putting together some more tutorials, and the one that I keep coming back to is how a beginner in XForms would actually get going. What technologies can we assume they know, and therefore build on, when presenting to them how to build an XForm? Do we start with something akin to an HTML form, and then make it more complex? Or do we start with the notion of an application, say like with VB, and show how it can be built more easily?

I felt recently that we weren't really serving the newcomer well, so I thought we should start with what an HTML programmer would know, and build on that. But at the same time, I also felt that the usual way of doing things didn't really give a flavour of what is possible with XForms, and they certainly don't deal with the type of applications that people are interested in these days.

So, rather than doing the usual order-form-shopping-basket-invoice thing, I thought that the modern programmer might be more interested in things RESTful, social, and perhaps map-full.

As luck would have it, I was also looking for a convenient way to save bookmarks to del.icio.us. I like being able to put links there when I come across something interesting, but I don't like the way that the forms on the site itself mess up my browser history. Even the couple of downloadable toolbars that are knocking around link through to this same interface. However, since del.icio.us has a nice simple RESTful API, things looked like they could be coming together.

I therefore put together a simple XForm that saved a bookmark to del.icio.us. Since it uses REST it's in effect an XForms version of a simple HTML GET form. The main difference is that by using the replace="instance" feature of XForms we don't need to navigate away from our form.

Of course this is not a lot of use in a browser since the form is occupying the space where we want the page we are looking at to be. But if we move the form out of the way into a side-bar, things start to get interesting. And if we add to that a little bit of code to obtain the document title and any metadata from the main page, you have the possibility of saving a full bookmark with tags in only one click of the mouse.

Once the form was moved into the side-bar it opened up a number of areas to experiment with. For example, if there is a description in the metadata this will be copied to the extended field in del.icio.us. But if you have highlighted some text in the document then this will be used instead. It's a very convenient way to save a bookmark but at the same time draw attention to why you have saved it (by the next day I have usually forgotten).

Another area I've experimented with is adding personal tags that indicate why I've saved the link. I've just put 'To Blog' and 'To Read' in as options at the moment, to see how this works out. But I think this could be an interesting area to continue developing. (The tags used are actually "My/ToBlog" and "My/ToRead", as suggested by Leigh Dodds. I thought I may as well begin with tags that someone else has used.)

If you fancy giving this little application a whirl then you are best off getting version 1.3.5 of formsPlayer from the download area of our site.

Once you have the new version, simply go to the configuration form. This is just an XForm, and it doesn't need to copy anything from our server--i.e., it doesn't do any component installation, since bar installation just involves calling some built in XPath functions in formsPlayer. After successful installation you will need to open a new browser, and then you will have an option formsPlayer Bookmark Manager in the Explorer Bar menu, under the View menu of IE.

The buttons on the form are pretty straightforward; you can save your link and data or cancel. You'll see in the screenshot above that there is a refresh button; this reloads the title and metadata from the page currently in the browser, which means that you can navigate away as much as you like, and then just press refresh when you want to fill the fields from the main browser.

One final touch is that you can also use the formsPlayer RSS reader to load your bookmarks into another side-bar, and make them available as you browse.

I plan to expand the bar with other useful features, so any feedback would be appreciated.

(An additional feature has been added--using Google Suggest as a source of tags.)


Tags: | | | | | |