/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is mozCC/ccRdf
 *
 * The Initial Developer of the Original Code is
 * Nathan R. Yergler.
 * Portions created by the Initial Developer are Copyright (C) 2004
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 * Nathan R. Yergler <nathan@yergler.net>
 *
 * ***** END LICENSE BLOCK ***** */

/* ccrdf.js
 * Creative Commons RDF parsing/manipulation support
 *
 * $Id: ccrdf.js,v 1.5 2004/01/20 16:21:23 nathan Exp $
 */

RDF = Components.classes['@mozilla.org/rdf/rdf-service;1'].
      getService(Components.interfaces.nsIRDFService);

/* rdfDict
 *  Provides a dictionary-like wrapper around a set of RDF triples with a
 *  common subject.  In addition to the standard dictionary interface
 *  provides convenience methods for manipulating the triples.
 **/
function rdfDict(subject, datasource) {

  this.subject = subject
  this.store = datasource

  // method definitions
  this.asString = asString
  this.about    = about
  this.__getvalues = __getvalues
  this.keys = keys
  this.getFirst = getFirst
  this.getAll = getAll
  this.length = length
  this.contains = contains

  function asString() {
  } // asString

  function about() {
    return this.subject.Value
  } // about

  function __getvalues(key) {

    values = new Array();

    objects = this.store.GetTargets(this.subject, RDF.GetResource(key), true);
    while (objects.hasMoreElements()) {
      current = objects.getNext();
      try {
         current.QueryInterface(Components.interfaces.nsIRDFResource);

         values.push(current);
      } catch(e) {
         // no resource interface for some reason -- forget it
      } // catch...

    } // while more elements

    return values;
  } // __getvalues

  function keys() {
    keys = new Array();

    resources = this.store.ArcLabelsOut(this.subject);
    while (resources.hasMoreElements()) {
      current = resources.getNext();
      current.QueryInterface(Components.interfaces.nsIRDFResource);

      keys.push(current);
    } // while more keys

    return keys;

  } // keys

  function getFirst(key) {
    return this.__getvalues(key)[0];
  } // getFirst

  function getAll(key) {
    return this.__getvalues(key);
  } // getAll

  function length() {
    // return the number of keys/predicates
    return (this.keys().length);
  } // length

  function contains(key) {
    return (this.__getvalues(key).length > 0);
  } // contains

} // rdfDict

function ccLicense (subject, datasource) {
  this.subject = subject
  this.store   = datasource

  // method definitions
  this.isPublicDomain = isPD

  function isPD() {
    return false;
  } // isPD

} // ccLicense
ccLicense.prototype = new rdfDict;

function ccWork (subject, datasource) {

  this.subject = subject
  this.store = datasource

  // method definitions
  this.licenses = licenses

  function licenses() {
    licenses = new Array();

    // make sure the source contains data
    if (this.store == null) {
       return licenses;
    } // if store is null
    
    source_licenses = this.store.GetTargets(
         this.subject,
         RDF.GetResource('http://web.resource.org/cc/license'), true);

    while (source_licenses.hasMoreElements()) {
      curr_license = source_licenses.getNext();
      curr_license.QueryInterface(Components.interfaces.nsIRDFResource);

      licenses.push(new ccLicense(curr_license, this.store));
    } // while has more elements

    return licenses;

  } // licenses

} // ccWork
ccWork.prototype = new rdfDict;

function ccRdf() {

  this.store = null;

  // method definitions
  this.parse    = parse;
  this.output   = output;
  this.works    = works;
  this.licenses = licenses;

  function parse(rdfString, uri) {

    xml = '@mozilla.org/rdf/datasource;1?name=in-memory-datasource';
    datasource = Components.classes[xml].
             createInstance(Components.interfaces.nsIRDFDataSource);

    // Used to create a URI below
    ios = Components.classes["@mozilla.org/network/io-service;1"].
      getService(Components.interfaces.nsIIOService);
    xmlParser = '@mozilla.org/rdf/xml-parser;1';
    parser = Components.classes[xmlParser].
         createInstance(Components.interfaces.nsIRDFXMLParser);

    uri = ios.newURI(uri || "http://mozcc.yergler.net/#", null, null);

    // Entire RDF File stored in a string
    parser.parseString(datasource,uri,rdfString);

    // Parsed string data now resides in the datasource
    this.store = datasource

  } // parse

  function output() {
  } // output

  function works() {

    works = new Array();

    // make sure the source contains data
    if (this.store == null) {
       return works;
    } // if store is null
    
    source_works = this.store.GetSources(
         RDF.GetResource('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
         RDF.GetResource('http://web.resource.org/cc/Work'), true);

    while (source_works.hasMoreElements()) {
      curr_work = source_works.getNext();
      curr_work.QueryInterface(Components.interfaces.nsIRDFResource);

      works.push(new ccWork(curr_work, this.store));
    } // while has more elements

    return works;

  } // works
  
  function licenses() {

    licenses = new Array();

    // make sure the source contains data
    if (this.store == null) {
       return licenses;
    } // if store is null
    
    source_licenses = this.store.GetSources(
         RDF.GetResource('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
         RDF.GetResource('http://web.resource.org/cc/License'), true);

    while (source_licenses.hasMoreElements()) {
      curr_license = source_licenses.getNext();
      curr_license.QueryInterface(Components.interfaces.nsIRDFResource);

      licenses.push(new ccLicense(curr_license, this.store));
    } // while has more elements

    return licenses;

  } // licenses

} // ccRdf

