Tuesday, January 30, 2007

del.icio.us bookmarks extension for FireFox

I'm an occasional, rather than compulsive, user of del.icio.us bookmarks. Nonetheless, whenever I reinstall FireFox, the del.icio.us toolbar is one of the few extensions I install automatically. I did this last week after reinstalling FireFox on one of my Linux machines. The installer seemed to have been updated from last time I went through this operation, but hey, stuff changes. Clicked OK on the buttons yada yada. Got the new del.icio.us Firefox extension, and boy has it changed.

So what does it do? Well, it uploads all of your FF bookmarks to your del.icio.us account, then replaces the FF bookmarks menu, and sidebar with its new, better version. All of your bookmarks are still in there, somewhere, but they appear as del.icio.us bookmarked entries. As a side-effect, if a given URL is already tagged by other users, you'll get those tags for free. So that's kind-of nice. What totally sucks is that the process throws away your existing category structure. Now, I'm the first to admit that I tend to the overly analytical. My Myers-Briggs is INTJ. My bookmarks are nested in folders up to four deep. The frequently used ones are near the top of the hierarchy, but, most of all, I know where they are. Once I'd del.icio.us-toolbar'ed my bookmarks, all that structure was gone. I was left with two flat lists, one of 980 bookmark URL's and one some several hundred tags that apply to those bookmarks. There is a category structure you can build (del.icio.us calls them bundles), but it only applies to tags, not bookmarks. So there was no way to manually re-create my nested structure.

From a usability point of view, the tool bar is nicely implemented, but, for me at least, completely unusable. I imagine that if you have a user whose bookmarks are already in one thumping great flat list, the auto-tagging feature will add some discernable value. For me though, it was a massive step backwards. It's a shame, because I believe in the value of metadata. The problem is that you really make people work to find stuff they've added. I don't want to have to type in search terms to locate the bookmark to my local weather forecast.

A saving grace is that uninstalling the extension gives a dialogue that offers to restore your bookmarks back to the way they were. This worked seamlessly. Apparently, the "classic" version of the toolbar is still available, so I'm going to try to track that down now.

del.icio.us: broken.

Ant problem: no class def SerializerTrace

I've started on a new project at work, where existing work has been done by colleagues doing Java development on Windows. Since I want to stick to my Linux environment, I'm trying to use the existing build scripts on Linux. The ant script works fine under Windows, but when I try to run the Ant xslt task on my FC5 machine (or RHEL 4, same thing happens), I get:

build.xml:74: The following error occurred while executing this line:
java.lang.NoClassDefFoundError: org/apache/xml/serializer/SerializerTrace

Now my Ant is installed via JPackage, and has all of its dependencies up-to-date. Double check, and, yup, xalan is installed and should provide all of the dependencies for the xslt Ant task. Google for answers, and it seems that there has been a packaging change in xalan 2.7, thereby confusing Ant (ants do have very small brains). This wiki page from the SipX project gives the necessary clue and recipe. Ant needs to be told to look for xalan-j2-serializer.jar, which can be achieved by dropping a file into /etc/ant.d. I'm not entirely clear what /etc/ant.d is doing, but this works for me:

root@rowan-8 ~
# cd /etc/ant.d

root@rowan-8 /etc/ant.d
# echo xalan-j2-serializer.jar > xslt

It doesn't matter what the file is called, it just needs to have the jar name in it. Presumably at some point the dependency issue will get sorted out cleanly. In the meantime, that's another minor but irritating roadblock out of the way.

Wednesday, January 17, 2007

Editable houses?

Consider: edit the config file ... refactor your house. Cool. May not work on if you live in a high-rise tower! I want one, especially if can do plumbing too. Via Kurzweil.

Jena tip: get the OWL class of a Resource or Individual

This is a frequently asked question that I'm going to address here and feed to future seekers after truth by the power of Google. In an OWL ontology (or, equivalently RDFS or DAML, but I'm just going to talk about OWL here for simplicity), you might find something like this:

<ex:Dog rdf:ID="deputy_dawg">

We have an OWL class ex:Dog (not shown), and one instance of that class: an individual whose URI is the XML base with deputy_dawg appended. So, if the xml:base is http://example.com/crimefighters#, the URI will be http://example.com/crimefighters#deputy_dawg. Now, suppose using Jena we have a reference to that resource. The frequently-asked question is: "how do I get the OWL classes for the resource?". Note that it really is OWL classes plural. We'll come back to this point in a bit. First let's do some setup.

An RDF resource is some thing, identified by zero or more URI's, about which we can make statements in a binary predicate form (e.g. "thing has-name Deputy""). In Jena, RDF resources are represented by the Resource class. The main RDF API, com.hp.hpl.jena.rdf.model provides classes and methods for manipulating resources and their properties. However, when working with OWL ontologies, there's a convenience API that extends the capabilities of the core RDF API. This is in com.hp.hpl.jena.ontology, and for convenience we'll call it the OntAPI. OntAPI has a Java class OntResource for representing general resources, and specialisations (Java sub-classes) of OntResource for resources that have special roles. So an resource denoting an OWL class has a convenience Java class OntClass, while a resource denoting an individual (such as our hapless canine lawman) is represented by the Java class Individual. So our question can be reformulated: get the OntClass resources denoting the OWL classes describing a given OntResource.

The primary method for doing this listRDFTypes. Why RDF types, not listOWLClasses()? The rationale is that the link from an individual to its OWL Class, RDFS class, etc, is via the RDF property rdf:type. However, this has proved confusing to some users, so I may add listOWLClasses() as an alias in a future release of Jena. Why listRDFTypes rather than getRDFType? In fact, getRDFType does exist, but isn't as useful as we might expect, for reasons discussed below. So let's see an example:

String NS = "http://example.com/crimefighters#"
OntModel m = ...   // assume this is the Jena model we're using

Individual dd = m.getIndividual( NS + "deputy_dawg" );

for (Iterator i = dd.listRDFTypes(false); i.hasNext(); ) {
    Resource cls = (Resource) i.next();
    System.out.println( "deputy_dawg has rdf:type " + cls );

This produces the output:

deputy_dawg has rdf:type http://example.com/crimefighters#Dog
deputy_dawg has rdf:type http://www.w3.org/2002/07/owl#Thing

Why does owl:Thing appear there? Simply put, it's an entailment added by the reasoner. All OWL classes are subclasses of owl:Thing. So any resource that has rdf:type T also has rdf:type owl:Thing by subsumption. In general, listRDFTypes will list all of the type statements in the model, no matter whether they were asserted or inferred. Unless the model was configured without a reasoner, there will normally be more than one rdf:type per resource, sometimes quite a lot. This is the reason why listRDFTypes is preferred: getRDFType will non-deterministically pick one of the available rdf:type's if there is more than one available. The caller has no control over which will be picked.

It's often convenient to have only the most specific type of an individual. This is what the Boolean direct flag denotes: if set to true, only the direct (most immediate) type statements are returned. We'll illustrate this by modifying the example slightly, starting with the ontology itself:

<owl:Class rdf:ID="Ally" />
<owl:Class rdf:ID="Dog">
    <owl:Class rdf:ID="FaithfulFriend" />

<ex:Dog rdf:ID="deputy_dawg">
  <rdf:type rdf:resource="#Ally" />

Now the code:

for (Iterator i = dd.listRDFTypes( false ); i.hasNext(); ) {
  Resource cls = (Resource) i.next();
  System.out.println( "deputy_dawg has non-direct rdf:type " + cls );
for (Iterator i = dd.listRDFTypes( true ); i.hasNext(); ) {
  Resource cls = (Resource) i.next();
  System.out.println( "deputy_dawg has direct rdf:type " + cls );

Which produces the following output:

deputy_dawg has non-direct rdf:type http://example.com/crimefighters#Ally
deputy_dawg has non-direct rdf:type http://example.com/crimefighters#Dog
deputy_dawg has non-direct rdf:type http://www.w3.org/2002/07/owl#Thing
deputy_dawg has non-direct rdf:type http://example.com/crimefighters#FaithfulFriend

deputy_dawg has direct rdf:type http://example.com/crimefighters#Ally
deputy_dawg has direct rdf:type http://example.com/crimefighters#Dog

because only Ally and Dog are immediate (i.e. non-subsumed) types.

OntResource defines a number of convenience methods for manipulating the OWL class of a resource. Besides listing and getting the type (listRDFType and getRDFType as above), there are also methods for adding a new type (addRDFType), replacing all existing type assertions (note: assertions, not entailments) with a new type (setRDFType) and testing the type (hasRDFType). For full details, please see the Javadoc.

del.icio.us: jena, tutorial, semanticweb.

Wednesday, January 10, 2007

WebS 2007

I'm on the programme committee for the 6th International Workshop on Web Semantics (WebS 2007), which has just made its call for papers. Submissions are due in March 2nd 2007, conference in Sept 2007. Semantic web, agents and ontologies – what more could be wanted! Submit ye all.

Thursday, January 04, 2007

jga: Generic Algorithms for Java

A useful find, via Elliote Rusty Harold: jga: Generic Algorithms for Java is a library for definining functor-style generic algorithms in Java. Examples here. I used SML on one project, years ago, and I've been enamoured of the functor-style of coding ever since. Of course, it's not nearly so fun if you can't write lambda-expressions and partial applications, but JGL does look like a useful tool that shouldn't have much, if anything, in the way of hidden costs.