The Mozilla
Organization
Our Mission
Who We Are
Getting Involved
Community
Editorials
What's New
Newsbot
Development
Roadmap
Module Owners
Blue Sky
Projects
Status
Tools
Products
Source Code
Binaries
Documentation
License Terms
Bug Reports
Quality
Search
Feedback


rdf: datasource howto

Contact: Chris Waterson (waterson@netscape.com)

This document is a cookbook that describes how to create a native, client-side datasource that works with Mozilla's RDF implementation. It supercedes (and borrows from) the original document put together by Robert Churchill.

What is a datasource?

[write me!]

Deciding on a vocabulary

The vocabulary is the set of properties that you will use to express relationships between elements (resources and literals) in your data model. The first question that you must answer is "should I use an existing vocabulary, or invent my own?" A reasonable answer is, "use an existing vocabulary unless you absolutely must invent your own." This will allow your datasource to be integrated with other datasources with a minimum of effort.

There are several existing vocabularies of note, including:

  • The RDF Schema Specification. This vocabulary is a "meta vocabulary" that is used to specify other vocabularies.
  • The Dublin Core. This vocabulary is useful for describing electronic resources. It contains elements for authorship, subject, publication date, etc.

Mapping your data to nodes and arcs

[write me!]

Implementing the nsIRDFDataSource interface

Your first chore will be to implement the nsIRDFDataSource interface. There are basically two approaches that you can take in this endeavor:

  1. Delegate to an inner proxy. For example, you may choose to delegate to the in-memory datasource, which is a generic datasource that implements nsIRDFDataSource.

    Typically, you provide a parser for reading in some sort of static storage (e.g., a data file); the parser translates the datafile into a series of calls to Assert() to set up the in-memory datasource. When Flush() is called, or the last reference to the datasource is released, a routine walks the in-memory datasource and re-serializes the graph back to the original file format. For examples of an implementation like this, look at the RDF/XML datasource or the bookmarks datasource.

    You may want to choose this implementation if your primary goal is to "wrap" a legacy data store. This implementation may cause problems if your data store can be modified "on the fly" by other agents.

  2. Implement the interface yourself. If you choose this route, you'll need to implement each of the nsIRDFDataStore methods "by hand". Although this is more work, it is really the only way to create a "live" datasource that may be changed by some outside agent.

    The file system datasource and local mail datasource are good examples of datasources that have been implemented this way.

    You'll probably need to choose this implementation if your datasource is "live", and may be modified or altered by some outside agent (e.g., new mail arriving). You may also need to choose this implementation if the data set which your datasource is modeling is too large to fit in to memory (e.g., the entire file system structure).

[More info on what each method needs to do here]

RDF Commands

    [Describe what commands are, and why you'd implement them.]

Registering the datasource component

A datasource is an XPCOM component. As such, it must (currently, see [1]) have:

  1. An XPCOM CLSID to identify the data source implementation
  2. An implementation class (that corresponds to the CLSID) whose code lives in a DLL. The DLL must be located in the XPCOM components directory
  3. A factory that is registered to an XPCOM ProgID in order to be instantiated from the repository.

Constructing a DLL for a component is beyond the scope of this document; the reader is referred to the RDF factory as a guideline.

Registering an RDF datasource is fairly simple: in the DLL's NSRegisterSelf() method, you simply call the component manager's RegisterComponent() method:

    extern "C" PR_IMPLEMENT(nsresult)
    NSRegisterSelf(nsISupports* aServiceManager, const char* aPath)
    {
       nsresult rv;
       ...
       // Assume compMgr refers to the component manager
       rv = compMgr->RegisterComponent(kMyDataSourceCID, 
                "My Data Source",
                NS_RDF_DATASOURCE_PROGID_PREFIX "my-datasource",
                aPath, PR_TRUE, PR_TRUE);
       ...
    }
    

Replace kMyDataSourceCID with your datasource's CLSID. Replace "My Data Source" with a descriptive string that should appear in the registry. Finally, replace "my-datasource" with a value appropriate for your datasource. This value, when prefixed with "rdf:", is a datasource identifier, and may be used with nsIRDFService::GetDataSource() to retrieve your datasource from the RDF service. For example, the above datasource would be accessable as follows:

    nsIRDFService* rdf;
    rv = nsServiceManager::GetService(kRDFServiceCID,
              kIRDFServiceIID,
              (nsISupports**) &rdf);
    
    if (NS_SUCCEEDED(rv)) {
        nsIRDFDataSource* myDataSource;
        rv = rdf->GetDataSource("rdf:my-datasource",
                     &myDataSource);
    
        if (NS_SUCCEEDED(rv)) {
            // ...do something to myDataSource here...
            NS_RELEASE(myDataSource);
        }
        nsServiceManager::ReleaseService(kRDFServiceCID, rdf);
    }
    

Displaying RDF as content

Now that you've gone through all this pain to expose your information as a datasource, you probably want to see it. Using XUL, you can display the contents of your datasource in a tree control, a menu, or a toolbar.

The following XUL fragment illustrates how to instantiate a tree control whose body is "rooted" to a resource (http://foo.bar.com/) that your datasource describes:

    <window
      xmlns:html="http://www.w3.org/TR/REC-html40"
      xmlns:rdf="http://www.w3.org/TR/WD-rdf-syntax#"
      xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    
      <tree datasources="rdf:my-datasource">
        <treecol rdf:resource="http://home.netscape.com/NC-rdf#Name" />
        <treecol rdf:resource="http://home.netscape.com/NC-rdf#URL" />
        <treehead>
          <treeitem>
            <treecell>Name</treecell>
            <treecell>URL</treecell>
          </treeitem>
        </treehead>
    
        <treebody id="http://foo.bar.com/" 
                  containment="http://www.foo.com/RDF#child" />
      </tree>
    
    </window>
    

The important "magic attributes" have been called out in bold, above:

  • datasources="rdf:my-datasource". This is a space-separated list that may include internal XPCOM datasource "identifiers" (as described above) and URIs for local or remote RDF/XML documents. Each datasource that is listed will be loaded, and the assertions contained in the datasource will be made available to the tree control for display.

  • treecol rdf:resource="...". This specifies the property that will be traversed to compute the cell value for each row in the tree control.

  • <treebody id="..." containment="...">. The id="..." specifies the resource that "roots" the tree, and the containment="..." specifies the property (or properties, if more than one is specified) that will be treated as indicating "childhood".

[example here]


1. As of this writing, it is not currently possible to implement JavaScript XPCOM components; however, it may soon be possible to do so via XPConnect.

Last Modified: $Id: datasource-howto.html,v 1.2 1999/04/13 19:06:18 waterson%netscape.com Exp $



Copyright © 1998 The Mozilla Organization.