10.5. JSLib RDF Files

Working with actual RDF files is not easy. However, JSLib (http://jslib.mozdev.org) provides an RDF file library that can help you develop an RDF-based application. The library provides many types of error checking, as well as a friendly abstraction away from the RDF/XML interfaces of Mozilla (see Section 10.3.11, later in this chapter). Example 10-12 shows some common uses of the RDFFile class in JSLib. This functionality can be used in situations in which you have data in RDF that you want to pull out "manually" and use piece by piece (rather than as a whole datasource in a template).

Example 10-12. Creating and modifying an RDF file using JSLib

var rdfFileURL = 'chrome://jarfly/content/jar.rdf';
var gTreeBody = null;
var gListbox = null;
var gRDF = null;
function onload( )
{
  fileUtils = new FileUtils( );
  path = fileUtils.chrome_to_path(rdfFileURL);
  if(navigator.platform == "Win32") {
    path = path.replace(/\//g,"\\"); 
    // Only needed on Windows, until JSLib is fixed
  }
  gRDF = new RDFFile(path,'jar:flies','http://mozdev.org/fly-rdf#');
  gTreeBody = document.getElementById('tb');
  gTreeBody.database.AddDataSource(gRDF.dsource);
  gListbox  = document.getElementById('list');
  gListbox.database.AddDataSource(gRDF.dsource);
  rebuildLists( );
}
function rebuildLists( )
{
  gTreeBody.builder.rebuild( );
  gListbox.builder.rebuild( );
}
function update( )
{
  name      = document.getElementById('nameField').value;
  color     = document.getElementById('colorField').value;
  quantity  = document.getElementById('quantityField').value;
  seqNumber = -1;
  del       = false;
  replace   = false;
  if(document.getElementById('delete').checked)
    del = true;
  if(document.getElementById('replace').checked)
    replace = true;
  var seqLength = 0;
  if(gRDF.doesSeqExist('types'))
  {
    seqLength = gRDF.getSeqSubNodes('types').length;
    //if(del)gRDF.removeSeq('types',false);
  }
  else
    gRDF.addSeq('types');
  for(i=0;i<seqLength;i++)
  {
    tempItem = 'types:_' + (i+1);
    if(gRDF.getAttribute(tempItem,'name')==name)
      seqNumber = gRDF.getAttribute(tempItem,'number');
  }
  if(seqNumber == -1)
  {
    item = 'types:_' + (seqLength+1);
    gRDF.setAttribute(item,'name',name);
    gRDF.setAttribute(item,'number',seqLength+1);
  }
  else
  {
    item = 'types:_' + seqNumber;
    gRDF.setAttribute(item,'number',seqNumber);
  }
  if(color!='')
    gRDF.setAttribute(item,'color',color);
  if(quantity!='')
  {
    gRDF.setAttribute(item,'quantity',quantity);
    gRDF.setAttribute(item,'dead',calcDead(quantity,replace));
  }
  if(!del)
    gRDF.addNode(item);
  else
    gRDF.removeNode(item);
  gRDF.flush( );
  onload( );
}
function calcDead(quantity,replace)
{
  if(!replace)
  {
    v = parseInt( (quantity * Math.random( )) * 0.13 );
    return (v.toString( ));
  }
  else
    return 0;
}
function changeC(color)
{
  document.getElementById('colorField').value=color;
}
function changeQ(quantity)
{
  document.getElementById('quantityField').value=quantity;
}

This example contains a datasource that represents a collection of flies. These flies are built up dynamically with JavaScript objects from the RDF library, which represent the datasource itself (gRDF = new RDFFile), methods that view and update the data (if(gRDF.getAttribute(tempItem,'name')==name), and utilities that make work with RDF files easier (path = fileUtils.chrome_to_path(rdfFileURL)).

Example 10-13 initializes and updates a file after it changes.

Example 10-13. Initialization

var rdfFileURL = 'chrome://jarfly/content/jar.rdf';
var gTreeBody = null;
var gListbox = null;
var gRDF = null;
function onload( )
{
  fileUtils = new FileUtils( );
  path = fileUtils.chrome_to_path(rdfFileURL);
  if(navigator.platform == "Win32") {
    path = path.replace(/\//g,"\\"); 
    // Only needed on Windows, until JSLib is fixed
  }
  gRDF = new RDFFile(path,'jar:flies','http://mozdev.org/fly-rdf#');

In Example 10-13, the file URL is set to an RDF file in the chrome area. Note that both a <tree> and a <listbox>, which display the same data in different ways, will be updated with the same datasource. The onload function is called after the main XUL document is loaded. A class called FileUtils is initialized, which will create a path to the RDF file. If the file doesn't already exist, JSLib automatically creates it.

Finally, the RDFFile is created by using the path and a root resource identifier, and the "xFly" namespace is used for the data references. Example 10-14 shows that the RDF file is ready to have its data added and deleted.

Example 10-14. Data updating

function update( )
{
  ...
  var seqLength = 0;
  if(gRDF.doesSeqExist('types'))
  {
    seqLength = gRDF.getSeqSubNodes('types').length;
  }
  else
    gRDF.addSeq('types');
  for(i=0;i<seqLength;i++)
  {
    tempItem = 'types:_' + (i+1);
    if(gRDF.getAttribute(tempItem,'name')==name)
      seqNumber = gRDF.getAttribute(tempItem,'number');
  }
  if(seqNumber == -1)
  {
    item = 'types:_' + (seqLength+1);
    gRDF.setAttribute(item,'name',name);
    gRDF.setAttribute(item,'number',seqLength+1);
  }
  else
  {
    item = 'types:_' + seqNumber;
    gRDF.setAttribute(item,'number',seqNumber);
  }
  if(color!='')
    gRDF.setAttribute(item,'color',color);
  if(quantity!='')
  {
    gRDF.setAttribute(item,'quantity',quantity);
    gRDF.setAttribute(item,'dead',calcDead(quantity,replace));
  }
  if(!del)
    gRDF.addNode(item);
  else
    gRDF.removeNode(item);
  gRDF.flush( );
  onload( );

Example 10-14 contains a modified version of the update function. First, the function checks to see if a sequence called types is in the RDF file. If not, it creates one. Next, it appends an item to the sequence using type:_+(seqLength+1). The same type of container setup was described in the section Section 10.3.10, earlier in this chapter.

The update function then adds the color, quantity, and "dead" properties of that new item in the sequence. Next, it ensures that you actually want to add the item to the RDF file and flushes it out if not. It then recalls the onload function to update the template display.

These are the basics of using RDFFile. As you can see, using JSLib for RDF is often much easier than trying to implement a similar setup on your own. More information about RDFFile and the other JSLib libraries can be found at http://jslib.mozdev.org/.