Friday, February 8, 2002




SBook was the best address book ever. Unlike every other address book, SBook didn't force entries to conform to some set of fields. Instead, you simply typed whatever you wanted into an entry and SBook would take care of parsing out phone numbers, addresses, and email addresses (this was before the web). The best part was the search-- you simply started typing into the search field and SBook would refine/update the match list in real time. While it was written for the 68040 NeXT the matching and parsing functionality was incredibly fast-- realtime.

SBook is coming to OS X!! Same great speed, same great verstility. An alpha version can be downloaded from the SBook5 web site.

CodeFab has long had a web based contact manager; very convenient when you have access to the net, but completely useless when on the road and without a net connection. We have long had the ability to export to a text file, but sorting through hundreds of entries to find the right one could be tedious.

Turns out that SBook can import an XML document of a very simple format. What follows is a hunk of Java code that uses the JDOM API to produce content that is stuffed into an HTTP response. The resulting XML doc can be directly imported into SBook.

import org.jdom.*;
import org.jdom.output.*;
//
public class SBookExporter {
// this is copied directly from a WebObjects app.  Converting it to non-WebObjects
// should be trivial;  there is no magic here.
// Contact:  class containing your contact-- implement asSingleLargeString() to
//     return a text representation of the contact.
// This would have *some* whitespace, but Radio triple spaces if I do so...
//
    NSArray contactsToExport;
//
    public WOResponse generateResponse() {
        if ( (contactsToExport == null) || (contactsToExport.count() == 0) )
            return null;
//        
        WOResponse xmlResponse = new WOResponse();
//
        xmlResponse.setStatus(200);
        xmlResponse.setContent( generateDOMResponse() );
        xmlResponse.setHeader("Content-type", "text/xml");
//
        return xmlResponse;
    }
//
    public String generateDOMResponse() {
        return new XMLOutputter().outputString( generateJDOMResponse() );
    }
//
    public org.jdom.Document generateJDOMResponse() {
        Element rootElement = new Element( "entries" );
        Enumeration contactEnumerator = contactsToExport.objectEnumerator();
        DocType docType = new DocType("plist", "SYSTEM", "http://www.simson.net/sbook/sbook.dtd");
        Contact nextContact;
//
        while (contactEnumerator.hasMoreElements()) {
            nextContact = (Contact) contactEnumerator.nextElement();
            Element entryElement = new Element( "entry" );
            Element contactElement = new Element( "text" );
            contactElement.addContent( nextContact.asSingleLargeString() );
            entryElement.addContent(contactElement);
            rootElement.addContent(entryElement);
        }
//
        return new org.jdom.Document(rootElement, docType);
    }
}

9:32:42 AM