      1 /*
      2  * jQuery RDF @VERSION
      3  *
      4  * Copyright (c) 2008,2009 Jeni Tennison
      5  * Licensed under the MIT (MIT-LICENSE.txt)
      6  *
      7  * Depends:
      8  *  jquery.uri.js
      9  *  jquery.xmlns.js
     10  *  jquery.datatype.js
     11  *  jquery.curie.js
     12  *  jquery.json.js
     13  */
     14 /**
     15  * @fileOverview jQuery RDF
     16  * @author <a href="mailto:jeni@jenitennison.com">Jeni Tennison</a>
     17  * @copyright (c) 2008,2009 Jeni Tennison
     18  * @license MIT license (MIT-LICENSE.txt)
     19  * @version 1.0
     20  */
     21 /**
     22  * @exports $ as jQuery
     23  */
     24 /**
     25  * @ignore
     26  */
     27 (function ($) {
     28   var
     29     memResource = {},
     30     memBlank = {},
     31     memLiteral = {},
     32     memTriple = {},
     33     memPattern = {},
     34
     35     xsdNs = "http://www.w3.org/2001/XMLSchema#",
     36     rdfNs = "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
     37     rdfsNs = "http://www.w3.org/2000/01/rdf-schema#",
     38
     39     uriRegex = /^<(([^>]|\\>)*)>$/,
     40     literalRegex = /^("""((\\"|[^"])*)"""|"((\\"|[^"])*)")(@([a-z]+(-[a-z0-9]+)*)|\^\^(.+))?$/,
     41     tripleRegex = /(("""((\\"|[^"])*)""")|("(\\"|[^"]|)*")|(<(\\>|[^>])*>)|\S)+/g,
     42
     43     blankNodeSeed = databankSeed = new Date().getTime() % 1000,
     44     blankNodeID = function () {
     45       blankNodeSeed += 1;
     46       return 'b' + blankNodeSeed.toString(16);
     47     },
     48
     49     databankID = function () {
     50       databankSeed += 1;
     51       return 'data' + databankSeed.toString(16);
     52     },
     53     databanks = {},
     54
     55     documentQueue = {},
     56
     57     subject = function (subject, opts) {
     58       if (typeof subject === 'string') {
     59         try {
     60           return $.rdf.resource(subject, opts);
     61         } catch (e) {
     62           try {
     63             return $.rdf.blank(subject, opts);
     64           } catch (f) {
     65             throw "Bad Triple: Subject " + subject + " is not a resource: " + f;
     66           }
     67         }
     68       } else {
     69         return subject;
     70       }
     71     },
     72
     73     property = function (property, opts) {
     74       if (property === 'a') {
     75         return $.rdf.type;
     76       } else if (typeof property === 'string') {
     77         try {
     78           return $.rdf.resource(property, opts);
     79         } catch (e) {
     80           throw "Bad Triple: Property " + property + " is not a resource: " + e;
     81         }
     82       } else {
     83         return property;
     84       }
     85     },
     86
     87     object = function (object, opts) {
     88       if (typeof object === 'string') {
     89         try {
     90           return $.rdf.resource(object, opts);
     91         } catch (e) {
     92           try {
     93             return $.rdf.blank(object, opts);
     94           } catch (f) {
     95             try {
     96               return $.rdf.literal(object, opts);
     97             } catch (g) {
     98               throw "Bad Triple: Object " + object + " is not a resource or a literal " + g;
     99             }
    100           }
    101         }
    102       } else {
    103         return object;
    104       }
    105     },
    106
    107     testResource = function (resource, filter, existing) {
    108       var variable;
    109       if (typeof filter === 'string') {
    110         variable = filter.substring(1);
    111         if (existing[variable] && existing[variable] !== resource) {
    112           return null;
    113         } else {
    114           existing[variable] = resource;
    115           return existing;
    116         }
    117       } else if (filter === resource) {
    118         return existing;
    119       } else {
    120         return null;
    121       }
    122     },
    123
    124     findMatches = function (databank, pattern) {
    125       if (databank.union === undefined) {
    126         if (pattern.subject.type !== undefined) {
    127           if (databank.subjectIndex[pattern.subject] === undefined) {
    128             return [];
    129           }
    130           return $.map(databank.subjectIndex[pattern.subject], function (triple) {
    131             var bindings = pattern.exec(triple);
    132             return bindings === null ? null : { bindings: bindings, triples: [triple] };
    133           });
    134         } else if (pattern.object.type === 'uri' || pattern.object.type === 'bnode') {
    135           if (databank.objectIndex[pattern.object] === undefined) {
    136             return [];
    137           }
    138           return $.map(databank.objectIndex[pattern.object], function (triple) {
    139             var bindings = pattern.exec(triple);
    140             return bindings === null ? null : { bindings: bindings, triples: [triple] };
    141           });
    142         } else if (pattern.property.type !== undefined) {
    143           if (databank.propertyIndex[pattern.property] === undefined) {
    144             return [];
    145           }
    146           return $.map(databank.propertyIndex[pattern.property], function (triple) {
    147             var bindings = pattern.exec(triple);
    148             return bindings === null ? null : { bindings: bindings, triples: [triple] };
    149           });
    150         }
    151       }
    152       return $.map(databank.triples(), function (triple) {
    153         var bindings = pattern.exec(triple);
    154         return bindings === null ? null : { bindings: bindings, triples: [triple] };
    155       });
    156     },
    157
    158     mergeMatches = function (existingMs, newMs, optional) {
    159       return $.map(existingMs, function (existingM, i) {
    160         var compatibleMs = $.map(newMs, function (newM) {
    161           // For newM to be compatible with existingM, all the bindings
    162           // in newM must either be the same as in existingM, or not
    163           // exist in existingM
    164           var k, b, isCompatible = true;
    165           for (k in newM.bindings) {
    166             b = newM.bindings[k];
    167             if (!(existingM.bindings[k] === undefined ||
    168                   existingM.bindings[k] === b)) {
    169               isCompatible = false;
    170               break;
    171             }
    172           }
    173           return isCompatible ? newM : null;
    174         });
    175         if (compatibleMs.length > 0) {
    176           return $.map(compatibleMs, function (compatibleM) {
    177             return {
    178               bindings: $.extend({}, existingM.bindings, compatibleM.bindings),
    179               triples: unique(existingM.triples.concat(compatibleM.triples))
    180             };
    181           });
    182         } else {
    183           return optional ? existingM : null;
    184         }
    185       });
    186     },
    187
    188     registerQuery = function (databank, query) {
    189       var s, p, o;
    190       if (query.filterExp !== undefined && !$.isFunction(query.filterExp)) {
    191         if (databank.union === undefined) {
    192           s = typeof query.filterExp.subject === 'string' ? '' : query.filterExp.subject;
    193           p = typeof query.filterExp.property === 'string' ? '' : query.filterExp.property;
    194           o = typeof query.filterExp.object === 'string' ? '' : query.filterExp.object;
    195           if (databank.queries[s] === undefined) {
    196             databank.queries[s] = {};
    197           }
    198           if (databank.queries[s][p] === undefined) {
    199             databank.queries[s][p] = {};
    200           }
    201           if (databank.queries[s][p][o] === undefined) {
    202             databank.queries[s][p][o] = [];
    203           }
    204           databank.queries[s][p][o].push(query);
    205         } else {
    206           $.each(databank.union, function (i, databank) {
    207             registerQuery(databank, query);
    208           });
    209         }
    210       }
    211     },
    212
    213     resetQuery = function (query) {
    214       query.length = 0;
    215       query.matches = [];
    216       $.each(query.children, function (i, child) {
    217         resetQuery(child);
    218       });
    219       $.each(query.partOf, function (i, union) {
    220         resetQuery(union);
    221       });
    222     },
    223
    224     updateQuery = function (query, matches) {
    225       if (matches.length > 0) {
    226         $.each(query.children, function (i, child) {
    227           leftActivate(child, matches);
    228         });
    229         $.each(query.partOf, function (i, union) {
    230           updateQuery(union, matches);
    231         });
    232         $.each(matches, function (i, match) {
    233           query.matches.push(match);
    234           Array.prototype.push.call(query, match.bindings);
    235         });
    236       }
    237     },
    238
    239     filterMatches = function (matches, variables) {
    240       var i, bindings, triples, j, k, variable, value, nvariables = variables.length,
    241         newbindings, match = {}, keyobject = {}, keys = {}, filtered = [];
    242       for (i = 0; i < matches.length; i += 1) {
    243         bindings = matches[i].bindings;
    244         triples = matches[i].triples;
    245         keyobject = keys;
    246         for (j = 0; j < nvariables; j += 1) {
    247           variable = variables[j];
    248           value = bindings[variable];
    249           if (j === nvariables - 1) {
    250             if (keyobject[value] === undefined) {
    251               match = { bindings: {}, triples: triples };
    252               for (k = 0; k < nvariables; k += 1) {
    253                 match.bindings[variables[k]] = bindings[variables[k]];
    254               }
    255               keyobject[value] = match;
    256               filtered.push(match);
    257             } else {
    258               match = keyobject[value];
    259               match.triples = match.triples.concat(triples);
    260             }
    261           } else {
    262             if (keyobject[value] === undefined) {
    263               keyobject[value] = {};
    264             }
    265             keyobject = keyobject[value];
    266           }
    267         }
    268       }
    269       return filtered;
    270     },
    271
    272     renameMatches = function (matches, old) {
    273       var i, match, newMatch, keys = {}, renamed = [];
    274       for (i = 0; i < matches.length; i += 1) {
    275         match = matches[i];
    276         if (keys[match.bindings[old]] === undefined) {
    277           newMatch = {
    278             bindings: { node: match.bindings[old] },
    279             triples: match.triples
    280           };
    281           renamed.push(newMatch);
    282           keys[match.bindings[old]] = newMatch;
    283         } else {
    284           newMatch = keys[match.bindings[old]];
    285           newMatch.triples = newMatch.triples.concat(match.triples);
    286         }
    287       }
    288       return renamed;
    289     },
    290
    291     leftActivate = function (query, matches) {
    292       var newMatches;
    293       if (query.union === undefined) {
    294         if (query.top || query.parent.top) {
    295           newMatches = query.alphaMemory;
    296         } else {
    297           matches = matches || query.parent.matches;
    298           if ($.isFunction(query.filterExp)) {
    299             newMatches = $.map(matches, function (match, i) {
    300               return query.filterExp.call(match.bindings, i, match.bindings, match.triples) ? match : null;
    301             });
    302           } else if (query.filterExp !== undefined) {
    303             newMatches = mergeMatches(matches, query.alphaMemory, query.filterExp.optional);
    304           } else {
    305             newMatches = matches;
    306           }
    307         }
    308       } else {
    309         newMatches = $.map(query.union, function (q) {
    310           return q.matches;
    311         });
    312       }
    313       if (query.selections !== undefined) {
    314         newMatches = filterMatches(newMatches, query.selections);
    315       } else if (query.navigate !== undefined) {
    316         newMatches = renameMatches(newMatches, query.navigate);
    317       }
    318       updateQuery(query, newMatches);
    319     },
    320
    321     rightActivate = function (query, match) {
    322       var newMatches;
    323       if (query.filterExp.optional) {
    324         resetQuery(query);
    325         leftActivate(query);
    326       } else {
    327         if (query.top || query.parent.top) {
    328           newMatches = [match];
    329         } else {
    330           newMatches = mergeMatches(query.parent.matches, [match], false);
    331         }
    332         updateQuery(query, newMatches);
    333       }
    334     },
    335
    336     addToQuery = function (query, triple) {
    337       var match,
    338         bindings = query.filterExp.exec(triple);
    339       if (bindings !== null) {
    340         match = { triples: [triple], bindings: bindings };
    341         query.alphaMemory.push(match);
    342         rightActivate(query, match);
    343       }
    344     },
    345
    346     removeFromQuery = function (query, triple) {
    347       query.alphaMemory.splice($.inArray(triple, query.alphaMemory), 1);
    348       resetQuery(query);
    349       leftActivate(query);
    350     },
    351
    352     addToQueries = function (queries, triple) {
    353       $.each(queries, function (i, query) {
    354         addToQuery(query, triple);
    355       });
    356     },
    357
    358     removeFromQueries = function (queries, triple) {
    359       $.each(queries, function (i, query) {
    360         removeFromQuery(query, triple);
    361       });
    362     },
    363
    364     addToDatabankQueries = function (databank, triple) {
    365       var s = triple.subject,
    366         p = triple.property,
    367         o = triple.object;
    368       if (databank.union === undefined) {
    369         if (databank.queries[s] !== undefined) {
    370           if (databank.queries[s][p] !== undefined) {
    371             if (databank.queries[s][p][o] !== undefined) {
    372               addToQueries(databank.queries[s][p][o], triple);
    373             }
    374             if (databank.queries[s][p][''] !== undefined) {
    375               addToQueries(databank.queries[s][p][''], triple);
    376             }
    377           }
    378           if (databank.queries[s][''] !== undefined) {
    379             if (databank.queries[s][''][o] !== undefined) {
    380               addToQueries(databank.queries[s][''][o], triple);
    381             }
    382             if (databank.queries[s][''][''] !== undefined) {
    383               addToQueries(databank.queries[s][''][''], triple);
    384             }
    385           }
    386         }
    387         if (databank.queries[''] !== undefined) {
    388           if (databank.queries[''][p] !== undefined) {
    389             if (databank.queries[''][p][o] !== undefined) {
    390               addToQueries(databank.queries[''][p][o], triple);
    391             }
    392             if (databank.queries[''][p][''] !== undefined) {
    393               addToQueries(databank.queries[''][p][''], triple);
    394             }
    395           }
    396           if (databank.queries[''][''] !== undefined) {
    397             if (databank.queries[''][''][o] !== undefined) {
    398               addToQueries(databank.queries[''][''][o], triple);
    399             }
    400             if (databank.queries[''][''][''] !== undefined) {
    401               addToQueries(databank.queries[''][''][''], triple);
    402             }
    403           }
    404         }
    405       } else {
    406         $.each(databank.union, function (i, databank) {
    407           addToDatabankQueries(databank, triple);
    408         });
    409       }
    410     },
    411
    412     removeFromDatabankQueries = function (databank, triple) {
    413       var s = triple.subject,
    414         p = triple.property,
    415         o = triple.object;
    416       if (databank.union === undefined) {
    417         if (databank.queries[s] !== undefined) {
    418           if (databank.queries[s][p] !== undefined) {
    419             if (databank.queries[s][p][o] !== undefined) {
    420               removeFromQueries(databank.queries[s][p][o], triple);
    421             }
    422             if (databank.queries[s][p][''] !== undefined) {
    423               removeFromQueries(databank.queries[s][p][''], triple);
    424             }
    425           }
    426           if (databank.queries[s][''] !== undefined) {
    427             if (databank.queries[s][''][o] !== undefined) {
    428               removeFromQueries(databank.queries[s][''][o], triple);
    429             }
    430             if (databank.queries[s][''][''] !== undefined) {
    431               removeFromQueries(databank.queries[s][''][''], triple);
    432             }
    433           }
    434         }
    435         if (databank.queries[''] !== undefined) {
    436           if (databank.queries[''][p] !== undefined) {
    437             if (databank.queries[''][p][o] !== undefined) {
    438               removeFromQueries(databank.queries[''][p][o], triple);
    439             }
    440             if (databank.queries[''][p][''] !== undefined) {
    441               removeFromQueries(databank.queries[''][p][''], triple);
    442             }
    443           }
    444           if (databank.queries[''][''] !== undefined) {
    445             if (databank.queries[''][''][o] !== undefined) {
    446               removeFromQueries(databank.queries[''][''][o], triple);
    447             }
    448             if (databank.queries[''][''][''] !== undefined) {
    449               removeFromQueries(databank.queries[''][''][''], triple);
    450             }
    451           }
    452         }
    453       } else {
    454         $.each(databank.union, function (i, databank) {
    455           removeFromDatabankQueries(databank, triple);
    456         });
    457       }
    458     },
    459
    460     group = function (bindings, variables, base) {
    461       var variable = variables[0], grouped = {}, results = [], i, newbase;
    462       base = base || {};
    463       if (variables.length === 0) {
    464         for (i = 0; i < bindings.length; i += 1) {
    465           for (v in bindings[i]) {
    466             if (base[v] === undefined) {
    467               base[v] = [];
    468             }
    469             if ($.isArray(base[v])) {
    470               base[v].push(bindings[i][v]);
    471             }
    472           }
    473         }
    474         return [base];
    475       }
    476       // collect together the grouped results
    477       for (i = 0; i < bindings.length; i += 1) {
    478         key = bindings[i][variable];
    479         if (grouped[key] === undefined) {
    480           grouped[key] = [];
    481         }
    482         grouped[key].push(bindings[i]);
    483       }
    484       // call recursively on each group
    485       variables = variables.splice(1, 1);
    486       for (v in grouped) {
    487         newbase = $.extend({}, base);
    488         newbase[variable] = grouped[v][0][variable];
    489         results = results.concat(group(grouped[v], variables, newbase));
    490       }
    491       return results;
    492     },
    493
    494     queue = function (databank, url, callbacks) {
    495       if (documentQueue[databank.id] === undefined) {
    496         documentQueue[databank.id] = {};
    497       }
    498       if (documentQueue[databank.id][url] === undefined) {
    499         documentQueue[databank.id][url] = callbacks;
    500         return false;
    501       }
    502       return true;
    503     },
    504
    505     dequeue = function (databank, url, result, args) {
    506       var callbacks = documentQueue[databank.id][url];
    507       if ($.isFunction(callbacks[result])) {
    508         callbacks[result].call(databank, args);
    509       }
    510       documentQueue[databank.id][url] = undefined;
    511     },
    512
    513     unique = function( b ) {
    514       var a = [];
    515       var l = b.length;
    516       for(var i=0; i<l; i++) {
    517         for(var j=i+1; j<l; j++) {
    518           // If b[i] is found later in the array
    519           if (b[i] === b[j])
    520             j = ++i;
    521         }
    522         a.push(b[i]);
    523       }
    524       return a;
    525      };
    526
    527
    528   $.typedValue.types['http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral'] = {
    529     regex: /^.*$/m,
    530     strip: false,
    531     value: function (v) {
    532       return v;
    533     }
    534   };
    535
    536   /**
    537    * <p>Creates a new jQuery.rdf object. This should be invoked as a method rather than constructed using new; indeed you will usually want to generate these objects using a method such as {@link jQuery#rdf} or {@link jQuery.rdf#where}.</p>
    538    * @class <p>A jQuery.rdf object represents the results of a query over its {@link jQuery.rdf#databank}. The results of a query are a sequence of objects which represent the bindings of values to the variables used in filter expressions specified using {@link jQuery.rdf#where} or {@link jQuery.rdf#optional}. Each of the objects in this sequence has associated with it a set of triples that are the sources for the variable bindings, which you can get at using {@link jQuery.rdf#sources}.</p>
    539     * <p>The {@link jQuery.rdf} object itself is a lot like a {@link jQuery} object. It has a {@link jQuery.rdf#length} and the individual matches can be accessed using <code>[<var>n</var>]</code>, but you can also iterate through the matches using {@link jQuery.rdf#map} or {@link jQuery.rdf#each}.</p>
    540     * <p>{@link jQuery.rdf} is designed to mirror the functionality of <a href="http://www.w3.org/TR/rdf-sparql-query/">SPARQL</a> while providing an interface that's familiar and easy to use for jQuery programmers.</p>
    541    * @param {Object} [options]
    542    * @param {jQuery.rdf.databank} [options.databank] The databank that this query should operate over.
    543    * @param {jQuery.rdf.triple[]} [options.triples] A set of triples over which the query operates; this is only used if options.databank isn't specified, in which case a new databank with these triples is generated.
    544    * @param {Object} [options.namespaces] An object representing a set of namespace bindings. Rather than passing this in when you construct the {@link jQuery.rdf} instance, you will usually want to use the {@link jQuery.rdf#prefix} method.
    545    * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the query.
    546    * @returns {jQuery.rdf}
    547    * @example rdf = jQuery.rdf();
    548    * @see jQuery#rdf
    549    */
    550   $.rdf = function (options) {
    551     return new $.rdf.fn.init(options);
    552   };
    553
    554   $.rdf.fn = $.rdf.prototype = {
    555     /**
    556      * The version of rdfQuery.
    557      * @type String
    558      */
    559     rdfquery: '1.1',
    560
    561     init: function (options) {
    562       var databanks, i;
    563       options = options || {};
    564       /* must specify either a parent or a union, otherwise it's the top */
    565       this.parent = options.parent;
    566       this.union = options.union;
    567       this.top = this.parent === undefined && this.union === undefined;
    568       if (this.union === undefined) {
    569         if (options.databank === undefined) {
    570           /**
    571            * The databank over which this query operates.
    572            * @type jQuery.rdf.databank
    573            */
    574           this.databank = this.parent === undefined ? $.rdf.databank(options.triples, options) : this.parent.databank;
    575         } else {
    576           this.databank = options.databank;
    577         }
    578       } else {
    579         databanks = $.map(this.union, function (query) {
    580           return query.databank;
    581         });
    582         databanks = unique(databanks);
    583         if (databanks[1] !== undefined) {
    584           this.databank = $.rdf.databank(undefined, { union: databanks });
    585         } else {
    586           this.databank = databanks[0];
    587         }
    588       }
    589       this.children = [];
    590       this.partOf = [];
    591       this.filterExp = options.filter;
    592       this.selections = options.distinct;
    593       this.navigate = options.navigate;
    594       this.alphaMemory = [];
    595       this.matches = [];
    596       /**
    597        * The number of matches represented by the {@link jQuery.rdf} object.
    598        * @type Integer
    599        */
    600       this.length = 0;
    601       if (this.filterExp !== undefined) {
    602         if (!$.isFunction(this.filterExp)) {
    603           registerQuery(this.databank, this);
    604           this.alphaMemory = findMatches(this.databank, this.filterExp);
    605         }
    606       } else if (options.nodes !== undefined) {
    607         this.alphaMemory = [];
    608         for (i = 0; i < options.nodes.length; i += 1) {
    609           this.alphaMemory.push({
    610             bindings: { node: options.nodes[i] },
    611             triples: []
    612           });
    613         }
    614       }
    615       leftActivate(this);
    616       return this;
    617     },
    618
    619     /**
    620      * Sets or returns the base URI of the {@link jQuery.rdf#databank}.
    621      * @param {String|jQuery.uri} [base]
    622      * @returns A {@link jQuery.uri} if no base URI is specified, otherwise returns this {@link jQuery.rdf} object.
    623      * @example baseURI = jQuery('html').rdf().base();
    624      * @example jQuery('html').rdf().base('http://www.example.org/');
    625      * @see jQuery.rdf.databank#base
    626      */
    627     base: function (base) {
    628       if (base === undefined) {
    629         return this.databank.base();
    630       } else {
    631         this.databank.base(base);
    632         return this;
    633       }
    634     },
    635
    636     /**
    637      * Sets or returns a namespace binding on the {@link jQuery.rdf#databank}.
    638      * @param {String} [prefix]
    639      * @param {String} [namespace]
    640      * @returns {Object|jQuery.uri|jQuery.rdf} If no prefix or namespace is specified, returns an object providing all namespace bindings on the {@link jQuery.rdf.databank}. If a prefix is specified without a namespace, returns the {@link jQuery.uri} associated with that prefix. Otherwise returns this {@link jQuery.rdf} object after setting the namespace binding.
    641      * @example namespace = jQuery('html').rdf().prefix('foaf');
    642      * @example jQuery('html').rdf().prefix('foaf', 'http://xmlns.com/foaf/0.1/');
    643      * @see jQuery.rdf.databank#prefix
    644      */
    645     prefix: function (prefix, namespace) {
    646       if (namespace === undefined) {
    647         return this.databank.prefix(prefix);
    648       } else {
    649         this.databank.prefix(prefix, namespace);
    650         return this;
    651       }
    652     },
    653
    654     /**
    655      * Adds a triple to the {@link jQuery.rdf#databank} or another {@link jQuery.rdf} object to create a union.
    656      * @param {String|jQuery.rdf.triple|jQuery.rdf.pattern|jQuery.rdf} triple The triple, {@link jQuery.rdf.pattern} or {@link jQuery.rdf} object to be added to this one. If the triple is a {@link jQuery.rdf} object, the two queries are unioned together. If the triple is a string, it's parsed as a {@link jQuery.rdf.pattern}. The pattern will be completed using the current matches on the {@link jQuery.rdf} object to create multiple triples, one for each set of bindings.
    657      * @param {Object} [options]
    658      * @param {Object} [options.namespaces] An object representing a set of namespace bindings used to interpret CURIEs within the triple. Defaults to the namespace bindings defined on the {@link jQuery.rdf#databank}.
    659      * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the triple. Defaults to the base URI defined on the {@link jQuery.rdf#databank}.
    660      * @returns {jQuery.rdf} This {@link jQuery.rdf} object.
    661      * @example
    662      * var rdf = $.rdf()
    663      *   .prefix('dc', ns.dc)
    664      *   .prefix('foaf', ns.foaf)
    665      *   .add('<photo1.jpg> dc:creator <http://www.blogger.com/profile/1109404> .')
    666      *   .add('<http://www.blogger.com/profile/1109404> foaf:img <photo1.jpg> .');
    667      * @example
    668      * var rdfA = $.rdf()
    669      *   .prefix('dc', ns.dc)
    670      *   .add('<photo1.jpg> dc:creator "Jane"');
    671      * var rdfB = $.rdf()
    672      *   .prefix('foaf', ns.foaf)
    673      *   .add('<photo1.jpg> foaf:depicts "Jane"');
    674      * var rdf = rdfA.add(rdfB);
    675      * @see jQuery.rdf.databank#add
    676      */
    677     add: function (triple, options) {
    678       var query, databank;
    679       if (triple.rdfquery !== undefined) {
    680         if (triple.top) {
    681           databank = this.databank.add(triple.databank);
    682           query = $.rdf({ parent: this.parent, databank: databank });
    683           return query;
    684         } else if (this.top) {
    685           databank = triple.databank.add(this.databank);
    686           query = $.rdf({ parent: triple.parent, databank: databank });
    687           return query;
    688         } else if (this.union === undefined) {
    689           query = $.rdf({ union: [this, triple] });
    690           this.partOf.push(query);
    691           triple.partOf.push(query);
    692           return query;
    693         } else {
    694           this.union.push(triple);
    695           triple.partOf.push(this);
    696         }
    697       } else {
    698         if (typeof triple === 'string') {
    699           options = $.extend({}, { base: this.base(), namespaces: this.prefix(), source: triple }, options);
    700           triple = $.rdf.pattern(triple, options);
    701         }
    702         if (triple.isFixed()) {
    703           this.databank.add(triple.triple(), options);
    704         } else {
    705           query = this;
    706           this.each(function (i, data) {
    707             var t = triple.triple(data);
    708             if (t !== null) {
    709               query.databank.add(t, options);
    710             }
    711           });
    712         }
    713       }
    714       return this;
    715     },
    716
    717     /**
    718      * Removes a triple or several triples from the {@link jQuery.rdf#databank}.
    719      * @param {String|jQuery.rdf.triple|jQuery.rdf.pattern} triple The triple to be removed, or a {@link jQuery.rdf.pattern} that matches the triples that should be removed.
    720      * @param {Object} [options]
    721      * @param {Object} [options.namespaces] An object representing a set of namespace bindings used to interpret any CURIEs within the triple or pattern. Defaults to the namespace bindings defined on the {@link jQuery.rdf#databank}.
    722      * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the triple or pattern. Defaults to the base URI defined on the {@link jQuery.rdf#databank}.
    723      * @returns {jQuery.rdf} The {@link jQuery.rdf} object itself.
    724      * @example
    725      * var rdf = $('html').rdf()
    726      *   .prefix('foaf', ns.foaf)
    727      *   .where('?person foaf:givenname ?gname')
    728      *   .where('?person foaf:family_name ?fname')
    729      *   .remove('?person foaf:family_name ?fname');
    730      * @see jQuery.rdf.databank#remove
    731      */
    732     remove: function (triple, options) {
    733       if (typeof triple === 'string') {
    734         options = $.extend({}, { base: this.base(), namespaces: this.prefix() }, options);
    735         triple = $.rdf.pattern(triple, options);
    736       }
    737       if (triple.isFixed()) {
    738         this.databank.remove(triple.triple(), options);
    739       } else {
    740         query = this;
    741         this.each(function (i, data) {
    742           var t = triple.triple(data);
    743           if (t !== null) {
    744             query.databank.remove(t, options);
    745           }
    746         });
    747       }
    748       return this;
    749     },
    750
    751     /**
    752      * Loads some data into the {@link jQuery.rdf#databank}
    753      * @param data
    754      * @param {Object} [options]
    755      * @see jQuery.rdf.databank#load
    756      */
    757     load: function (data, options) {
    758       var rdf = this,
    759         options = options || {},
    760         success = options.success;
    761       if (success !== undefined) {
    762         options.success = function () {
    763           success.call(rdf);
    764         }
    765       }
    766       this.databank.load(data, options);
    767       return this;
    768     },
    769
    770     /**
    771      * Creates a new {@link jQuery.rdf} object whose databank contains all the triples in this object's databank except for those in the argument's databank.
    772      * @param {jQuery.rdf} query
    773      * @see jQuery.rdf.databank#except
    774      */
    775     except: function (query) {
    776       return $.rdf({ databank: this.databank.except(query.databank) });
    777     },
    778
    779     /**
    780      * Creates a new {@link jQuery.rdf} object that is the result of filtering the matches on this {@link jQuery.rdf} object based on the filter that's passed into it.
    781      * @param {String|jQuery.rdf.pattern} filter An expression that filters the triples in the {@link jQuery.rdf#databank} to locate matches based on the matches on this {@link jQuery.rdf} object. If it's a string, the filter is parsed as a {@link jQuery.rdf.pattern}.
    782      * @param {Object} [options]
    783      * @param {Object} [options.namespaces] An object representing a set of namespace bindings used to interpret any CURIEs within the pattern. Defaults to the namespace bindings defined on the {@link jQuery.rdf#databank}.
    784      * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the pattern. Defaults to the base URI defined on the {@link jQuery.rdf#databank}.
    785      * @param {boolean} [options.optional] Not usually used (use {@link jQuery.rdf#optional} instead).
    786      * @returns {jQuery.rdf} A new {@link jQuery.rdf} object whose {@link jQuery.rdf#parent} is this {@link jQuery.rdf}.
    787      * @see jQuery.rdf#optional
    788      * @see jQuery.rdf#filter
    789      * @see jQuery.rdf#about
    790      * @example
    791      * var rdf = $.rdf()
    792      *   .prefix('foaf', ns.foaf)
    793      *   .add('_:a foaf:givenname   "Alice" .')
    794      *   .add('_:a foaf:family_name "Hacker" .')
    795      *   .add('_:b foaf:givenname   "Bob" .')
    796      *   .add('_:b foaf:family_name "Hacker" .')
    797      *   .where('?person foaf:family_name "Hacker"')
    798      *   .where('?person foaf:givenname "Bob");
    799      */
    800     where: function (filter, options) {
    801       var query, base, namespaces, optional;
    802       options = options || {};
    803       if (typeof filter === 'string') {
    804         base = options.base || this.base();
    805         namespaces = $.extend({}, this.prefix(), options.namespaces || {});
    806         optional = options.optional || false;
    807         filter = $.rdf.pattern(filter, { namespaces: namespaces, base: base, optional: optional });
    808       }
    809       query = $.rdf($.extend({}, options, { parent: this, filter: filter }));
    810       this.children.push(query);
    811       return query;
    812     },
    813
    814     /**
    815      * Creates a new {@link jQuery.rdf} object whose set of bindings might optionally include those based on the filter pattern.
    816      * @param {String|jQuery.rdf.pattern} filter An pattern for a set of bindings that might be added to those in this {@link jQuery.rdf} object.
    817      * @param {Object} [options]
    818      * @param {Object} [options.namespaces] An object representing a set of namespace bindings used to interpret any CURIEs within the pattern. Defaults to the namespace bindings defined on the {@link jQuery.rdf#databank}.
    819      * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the pattern. Defaults to the base URI defined on the {@link jQuery.rdf#databank}.
    820      * @returns {jQuery.rdf} A new {@link jQuery.rdf} object whose {@link jQuery.rdf#parent} is this {@link jQuery.rdf}.
    821      * @see jQuery.rdf#where
    822      * @see jQuery.rdf#filter
    823      * @see jQuery.rdf#about
    824      * @example
    825      * var rdf = $.rdf()
    826      *   .prefix('foaf', 'http://xmlns.com/foaf/0.1/')
    827      *   .prefix('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#')
    828      *   .add('_:a  rdf:type        foaf:Person .')
    829      *   .add('_:a  foaf:name       "Alice" .')
    830      *   .add('_:a  foaf:mbox       <mailto:alice@example.com> .')
    831      *   .add('_:a  foaf:mbox       <mailto:alice@work.example> .')
    832      *   .add('_:b  rdf:type        foaf:Person .')
    833      *   .add('_:b  foaf:name       "Bob" .')
    834      *   .where('?x foaf:name ?name')
    835      *   .optional('?x foaf:mbox ?mbox');
    836      */
    837     optional: function (filter, options) {
    838       return this.where(filter, $.extend({}, options || {}, { optional: true }));
    839     },
    840
    841     /**
    842      * Creates a new {@link jQuery.rdf} object whose set of bindings include <code>property</code> and <code>value</code> for every triple that is about the specified resource.
    843      * @param {String|jQuery.rdf.resource} resource The subject of the matching triples.
    844      * @param {Object} [options]
    845      * @param {Object} [options.namespaces] An object representing a set of namespace bindings used to interpret the resource if it's a CURIE. Defaults to the namespace bindings defined on the {@link jQuery.rdf#databank}.
    846      * @param {String|jQuery.uri} [options.base] The base URI used to interpret the resource if it's a relative URI (wrapped in <code><</code> and <code>></code>). Defaults to the base URI defined on the {@link jQuery.rdf#databank}.
    847      * @returns {jQuery.rdf} A new {@link jQuery.rdf} object whose {@link jQuery.rdf#parent} is this {@link jQuery.rdf}.
    848      * @see jQuery.rdf#where
    849      * @see jQuery.rdf#optional
    850      * @see jQuery.rdf#filter
    851      * @example
    852      * var rdf = $.rdf()
    853      *   .prefix('dc', ns.dc)
    854      *   .prefix('foaf', ns.foaf)
    855      *   .add('<photo1.jpg> dc:creator <http://www.blogger.com/profile/1109404> .')
    856      *   .add('<http://www.blogger.com/profile/1109404> foaf:img <photo1.jpg> .')
    857      *   .add('<photo2.jpg> dc:creator <http://www.blogger.com/profile/1109404> .')
    858      *   .add('<http://www.blogger.com/profile/1109404> foaf:img <photo2.jpg> .')
    859      *   .about('<http://www.blogger.com/profile/1109404>');
    860      */
    861     about: function (resource, options) {
    862       return this.where(resource + ' ?property ?value', options);
    863     },
    864
    865     /**
    866      * Creates a new {@link jQuery.rdf} object whose set of bindings include only those that satisfy some arbitrary condition. There are two main ways to call this method: with two arguments in which case the first is a binding to be tested and the second represents a condition on the test, or with one argument which is a function that should return true for acceptable bindings.
    867      * @param {Function|String} property <p>In the two-argument version, this is the name of a property to be tested against the condition specified in the second argument. In the one-argument version, this is a function in which <code>this</code> is an object whose properties are a set of {@link jQuery.rdf.resource}, {@link jQuery.rdf.literal} or {@link jQuery.rdf.blank} objects and whose arguments are:</p>
    868      * <dl>
    869      *   <dt>i</dt>
    870      *   <dd>The index of the set of bindings amongst the other matches</dd>
    871      *   <dt>bindings</dt>
    872      *   <dd>An object representing the bindings (the same as <code>this</code>)</dd>
    873      *   <dt>triples</dt>
    874      *   <dd>The {@link jQuery.rdf.triple}s that underly this set of bindings</dd>
    875      * </dl>
    876      * @param {RegExp|String} condition In the two-argument version of this function, the condition that the property's must match. If it is a regular expression, the value must match the regular expression. If it is a {@link jQuery.rdf.literal}, the value of the literal must match the property's value. Otherwise, they must be the same resource.
    877      * @returns {jQuery.rdf} A new {@link jQuery.rdf} object whose {@link jQuery.rdf#parent} is this {@link jQuery.rdf}.
    878      * @see jQuery.rdf#where
    879      * @see jQuery.rdf#optional
    880      * @see jQuery.rdf#about
    881      * @example
    882      * var rdf = $.rdf()
    883      *   .prefix('foaf', 'http://xmlns.com/foaf/0.1/')
    884      *   .add('_:a foaf:surname "Jones" .')
    885      *   .add('_:b foaf:surname "Macnamara" .')
    886      *   .add('_:c foaf:surname "O\'Malley"')
    887      *   .add('_:d foaf:surname "MacFee"')
    888      *   .where('?person foaf:surname ?surname')
    889      *     .filter('surname', /^Ma?c/)
    890      *       .each(function () { scottish.push(this.surname.value); })
    891      *     .end()
    892      *     .filter('surname', /^O'/)
    893      *       .each(function () { irish.push(this.surname.value); })
    894      *     .end();
    895      * @example
    896      * var rdf = $.rdf()
    897      *   .prefix('foaf', 'http://xmlns.com/foaf/0.1/')
    898      *   .add('_:a foaf:surname "Jones" .')
    899      *   .add('_:b foaf:surname "Macnamara" .')
    900      *   .add('_:c foaf:surname "O\'Malley"')
    901      *   .add('_:d foaf:surname "MacFee"')
    902      *   .where('?person foaf:surname ?surname')
    903      *   .filter(function () { return this.surname !== "Jones"; })
    904      */
    905     filter: function (property, condition) {
    906       var func, query;
    907       if (typeof property === 'string') {
    908         if (condition.constructor === RegExp) {
    909           /** @ignore func */
    910           func = function () {
    911             return condition.test(this[property].value);
    912           };
    913         } else {
    914           func = function () {
    915             return this[property].type === 'literal' ? this[property].value === condition : this[property] === condition;
    916           };
    917         }
    918       } else {
    919         func = property;
    920       }
    921       query = $.rdf({ parent: this, filter: func });
    922       this.children.push(query);
    923       return query;
    924     },
    925
    926     /**
    927      * Creates a new {@link jQuery.rdf} object containing one binding for each selected resource.
    928      * @param {String|Object} node The node to be selected. If this is a string beginning with a question mark the resources are those identified by the bindings of that value in the currently selected bindings. Otherwise, only the named resource is selected as the node.
    929      * @returns {jQuery.rdf} A new {@link jQuery.rdf} object.
    930      * @see jQuery.rdf#find
    931      * @see jQuery.rdf#back
    932      * @example
    933      * // returns an rdfQuery object with a pointer to <http://example.com/aReallyGreatBook>
    934      * var rdf = $('html').rdf()
    935      *   .node('<http://example.com/aReallyGreatBook>');
    936      */
    937     node: function (resource) {
    938       var variable, query;
    939       if (resource.toString().substring(0, 1) === '?') {
    940         variable = resource.toString().substring(1);
    941         query = $.rdf({ parent: this, navigate: variable });
    942       } else {
    943         if (typeof resource === 'string') {
    944           resource = object(resource, { namespaces: this.prefix(), base: this.base() });
    945         }
    946         query = $.rdf({ parent: this, nodes: [resource] });
    947       }
    948       this.children.push(query);
    949       return query;
    950     },
    951
    952     /**
    953      * Navigates from the resource identified by the 'node' binding to another node through the property passed as the argument.
    954      * @param {String|Object} property The property whose value will be the new node.
    955      * @returns {jQuery.rdf} A new {@link jQuery.rdf} object whose {@link jQuery.rdf#parent} is this {@link jQuery.rdf}.
    956      * @see jQuery.rdf#back
    957      * @see jQuery.rdf#node
    958      * @example
    959      * var creators = $('html').rdf()
    960      *   .node('<>')
    961      *   .find('dc:creator');
    962      */
    963     find: function (property) {
    964       return this.where('?node ' + property + ' ?object', { navigate: 'object' });
    965     },
    966
    967     /**
    968      * Navigates from the resource identified by the 'node' binding to another node through the property passed as the argument, like {jQuery.rdf#find}, but backwards.
    969      * @param {String|Object} property The property whose value will be the new node.
    970      * @returns {jQuery.rdf} A new {@link jQuery.rdf} object whose {@link jQuery.rdf#parent} is this {@link jQuery.rdf}.
    971      * @see jQuery.rdf#find
    972      * @see jQuery.rdf#node
    973      * @example
    974      * var people = $('html').rdf()
    975      *   .node('foaf:Person')
    976      *   .back('rdf:type');
    977      */
    978     back: function (property) {
    979       return this.where('?subject ' + property + ' ?node', { navigate: 'subject' });
    980     },
    981
    982     /**
    983      * Groups the bindings held by this {@link jQuery.rdf} object based on the values of the variables passed as the parameter.
    984      * @param {String[]} [bindings] The variables to group by. The returned objects will contain all their current properties, but those aside from the specified variables will be arrays listing the relevant values.
    985      * @returns {jQuery} A jQuery object containing objects representing the grouped bindings.
    986      * @example
    987      * // returns one object per person and groups all the names and all the emails together in arrays
    988      * var grouped = rdf
    989      *   .where('?person foaf:name ?name')
    990      *   .where('?person foaf:email ?email')
    991      *   .group('person');
    992      * @example
    993      * // returns one object per surname/firstname pair, with the person property being an array in the resulting objects
    994      * var grouped = rdf
    995      *   .where('?person foaf:first_name ?forename')
    996      *   .where('?person foaf:givenname ?surname')
    997      *   .group(['surname', 'forename']);
    998      */
    999     group: function (bindings) {
    1000       var grouped = {}, results = [], i, key, v;
    1001       if (!$.isArray(bindings)) {
    1002         bindings = [bindings];
    1003       }
    1004       return $(group(this, bindings));
    1005     },
    1006
    1007     /**
    1008      * Filters the variable bindings held by this {@link jQuery.rdf} object down to those listed in the bindings parameter. This mirrors the <a href="http://www.w3.org/TR/rdf-sparql-query/#select">SELECT</a> form in SPARQL.
    1009      * @param {String[]} [bindings] The variables that you're interested in. The returned objects will only contain those variables. If bindings is undefined, you will get all the variable bindings in the returned objects.
    1010      * @returns {Object[]} An array of objects with the properties named by the bindings parameter.
    1011      * @example
    1012      * var filtered = rdf
    1013      *   .where('?photo dc:creator ?creator')
    1014      *   .where('?creator foaf:img ?photo');
    1015      * var selected = rdf.select(['creator']);
    1016      */
    1017     select: function (bindings) {
    1018       var s = [], i, j;
    1019       for (i = 0; i < this.length; i += 1) {
    1020         if (bindings === undefined) {
    1021           s[i] = this[i];
    1022         } else {
    1023           s[i] = {};
    1024           for (j = 0; j < bindings.length; j += 1) {
    1025             s[i][bindings[j]] = this[i][bindings[j]];
    1026           }
    1027         }
    1028       }
    1029       return s;
    1030     },
    1031
    1032     /**
    1033      * Provides <a href="http://n2.talis.com/wiki/Bounded_Descriptions_in_RDF#Simple_Concise_Bounded_Description">simple concise bounded descriptions</a> of the resources or bindings that are passed in the argument. This mirrors the <a href="http://www.w3.org/TR/rdf-sparql-query/#describe">DESCRIBE</a> form in SPARQL.
    1034      * @param {(String|jQuery.rdf.resource)[]} bindings An array that can contain strings, {@link jQuery.rdf.resource}s or a mixture of the two. Any strings that begin with a question mark (<code>?</code>) are taken as variable names; each matching resource is described by the function.
    1035      * @returns {jQuery} A {@link jQuery} object that contains {@link jQuery.rdf.triple}s that describe the listed resources.
    1036      * @see jQuery.rdf.databank#describe
    1037      * @example
    1038      * $.rdf.dump($('html').rdf().describe(['<photo1.jpg>']));
    1039      * @example
    1040      * $('html').rdf()
    1041      *   .where('?person foaf:img ?picture')
    1042      *   .describe(['?photo'])
    1043      */
    1044     describe: function (bindings) {
    1045       var i, j, binding, resources = [];
    1046       for (i = 0; i < bindings.length; i += 1) {
    1047         binding = bindings[i];
    1048         if (binding.substring(0, 1) === '?') {
    1049           binding = binding.substring(1);
    1050           for (j = 0; j < this.length; j += 1) {
    1051             resources.push(this[j][binding]);
    1052           }
    1053         } else {
    1054           resources.push(binding);
    1055         }
    1056       }
    1057       return this.databank.describe(resources);
    1058     },
    1059
    1060     /**
    1061      * Returns a new {@link jQuery.rdf} object that contains only one set of variable bindings. This is designed to mirror the <a href="http://docs.jquery.com/Traversing/eq#index">jQuery#eq</a> method.
    1062      * @param {Integer} n The index number of the match that should be selected.
    1063      * @returns {jQuery.rdf} A new {@link jQuery.rdf} object with just that match.
    1064      * @example
    1065      * var rdf = $.rdf()
    1066      *   .prefix('foaf', 'http://xmlns.com/foaf/0.1/')
    1067      *   .add('_:a  foaf:name       "Alice" .')
    1068      *   .add('_:a  foaf:homepage   <http://work.example.org/alice/> .')
    1069      *   .add('_:b  foaf:name       "Bob" .')
    1070      *   .add('_:b  foaf:mbox       <mailto:bob@work.example> .')
    1071      *   .where('?x foaf:name ?name')
    1072      *   .eq(1);
    1073      */
    1074     eq: function (n) {
    1075       return this.filter(function (i) {
    1076         return i === n;
    1077       });
    1078     },
    1079
    1080     /**
    1081      * Returns a {@link jQuery.rdf} object that includes no filtering (and therefore has no matches) over the {@link jQuery.rdf#databank}.
    1082      * @returns {jQuery.rdf} An empty {@link jQuery.rdf} object.
    1083      * @example
    1084      * $('html').rdf()
    1085      *   .where('?person foaf:family_name "Hacker"')
    1086      *   .where('?person foaf:givenname "Alice"')
    1087      *   .each(...do something with Alice Hacker...)
    1088      *   .reset()
    1089      *   .where('?person foaf:family_name "Jones"')
    1090      *   .where('?person foaf:givenname "Bob"')
    1091      *   .each(...do something with Bob Jones...);
    1092      */
    1093     reset: function () {
    1094       var query = this;
    1095       while (query.parent !== undefined) {
    1096         query = query.parent;
    1097       }
    1098       return query;
    1099     },
    1100
    1101     /**
    1102      * Returns the parent {@link jQuery.rdf} object, which is equivalent to undoing the most recent filtering operation (such as {@link jQuery.rdf#where} or {@link jQuery.rdf#filter}). This is designed to mirror the <a href="http://docs.jquery.com/Traversing/end">jQuery#end</a> method.
    1103      * @returns {jQuery.rdf}
    1104      * @example
    1105      * $('html').rdf()
    1106      *   .where('?person foaf:family_name "Hacker"')
    1107      *   .where('?person foaf:givenname "Alice"')
    1108      *   .each(...do something with Alice Hacker...)
    1109      *   .end()
    1110      *   .where('?person foaf:givenname "Bob"')
    1111      *   .each(...do something with Bob Hacker...);
    1112      */
    1113     end: function () {
    1114       return this.parent;
    1115     },
    1116
    1117     /**
    1118      * Returns the number of matches in this {@link jQuery.rdf} object (equivalent to {@link jQuery.rdf#length}).
    1119      * @returns {Integer} The number of matches in this {@link jQuery.rdf} object.
    1120      * @see jQuery.rdf#length
    1121      */
    1122     size: function () {
    1123       return this.length;
    1124     },
    1125
    1126     /**
    1127      * Gets the triples that form the basis of the variable bindings that are the primary product of {@link jQuery.rdf}. Getting hold of the triples can be useful for understanding the facts that form the basis of the variable bindings.
    1128      * @returns {jQuery} A {@link jQuery} object containing arrays of {@link jQuery.rdf.triple} objects. A {@link jQuery} object is returned so that you can easily iterate over the contents.
    1129      * @example
    1130      * $('html').rdf()
    1131      *   .where('?thing a foaf:Person')
    1132      *   .sources()
    1133      *   .each(function () {
    1134      *     ...do something with the array of triples...
    1135      *   });
    1136      */
    1137     sources: function () {
    1138       return $($.map(this.matches, function (match) {
    1139         // return an array-of-an-array because arrays automatically get expanded by $.map()
    1140         return [match.triples];
    1141       }));
    1142     },
    1143
    1144     /**
    1145      * Dumps the triples that form the basis of the variable bindings that are the primary product of {@link jQuery.rdf} into a format that can be shown to the user or sent to a server.
    1146      * @param {Object} [options] Options that control the formatting of the triples. See {@link jQuery.rdf.dump} for details.
    1147      * @see jQuery.rdf.dump
    1148      */
    1149     dump: function (options) {
    1150       var triples = $.map(this.matches, function (match) {
    1151         return match.triples;
    1152       });
    1153       options = $.extend({ namespaces: this.databank.namespaces, base: this.databank.base }, options || {});
    1154       return $.rdf.dump(triples, options);
    1155     },
    1156
    1157     /**
    1158      * Either returns the item specified by the argument or turns the {@link jQuery.rdf} object into an array. This mirrors the <a href="http://docs.jquery.com/Core/get">jQuery#get</a> method.
    1159      * @param {Integer} [num] The number of the item to be returned.
    1160      * @returns {Object[]|Object} Returns either a single Object representing variable bindings or an array of such.
    1161      * @example
    1162      * $('html').rdf()
    1163      *   .where('?person a foaf:Person')
    1164      *   .get(0)
    1165      *   .subject
    1166      *   .value;
    1167      */
    1168     get: function (num) {
    1169       return (num === undefined) ? $.makeArray(this) : this[num];
    1170     },
    1171
    1172     /**
    1173      * Iterates over the matches held by the {@link jQuery.rdf} object and performs a function on each of them. This mirrors the <a href="http://docs.jquery.com/Core/each">jQuery#each</a> method.
    1174      * @param {Function} callback A function that is called for each match on the {@link jQuery.rdf} object. Within the function, <code>this</code> is set to the object representing the variable bindings. The function can take up to three parameters:
    1175      * <dl>
    1176      *   <dt>i</dt><dd>The index of the match amongst the other matches.</dd>
    1177      *   <dt>bindings</dt><dd>An object representing the variable bindings for the match, the same as <code>this</code>.</dd>
    1178      *   <dt>triples</dt><dd>An array of {@link jQuery.rdf.triple}s associated with the particular match.</dd>
    1179      * </dl>
    1180      * @returns {jQuery.rdf} The {@link jQuery.rdf} object.
    1181      * @see jQuery.rdf#map
    1182      * @example
    1183      * var rdf = $('html').rdf()
    1184      *   .where('?photo dc:creator ?creator')
    1185      *   .where('?creator foaf:img ?photo')
    1186      *   .each(function () {
    1187      *     photos.push(this.photo.value);
    1188      *   });
    1189      */
    1190     each: function (callback) {
    1191       $.each(this.matches, function (i, match) {
    1192         callback.call(match.bindings, i, match.bindings, match.triples);
    1193       });
    1194       return this;
    1195     },
    1196
    1197     /**
    1198      * Iterates over the matches held by the {@link jQuery.rdf} object and creates a new {@link jQuery} object that holds the result of applying the passed function to each one. This mirrors the <a href="http://docs.jquery.com/Traversing/map">jQuery#map</a> method.
    1199      * @param {Function} callback A function that is called for each match on the {@link jQuery.rdf} object. Within the function, <code>this</code> is set to the object representing the variable bindings. The function can take up to three parameters and should return some kind of value:
    1200      * <dl>
    1201      *   <dt>i</dt><dd>The index of the match amongst the other matches.</dd>
    1202      *   <dt>bindings</dt><dd>An object representing the variable bindings for the match, the same as <code>this</code>.</dd>
    1203      *   <dt>triples</dt><dd>An array of {@link jQuery.rdf.triple}s associated with the particular match.</dd>
    1204      * </dl>
    1205      * @returns {jQuery} A jQuery object holding the results of the function for each of the matches on the original {@link jQuery.rdf} object.
    1206      * @example
    1207      * var photos = $('html').rdf()
    1208      *   .where('?photo dc:creator ?creator')
    1209      *   .where('?creator foaf:img ?photo')
    1210      *   .map(function () {
    1211      *     return this.photo.value;
    1212      *   });
    1213      */
    1214     map: function (callback) {
    1215       return $($.map(this.matches, function (match, i) {
    1216         // in the callback, "this" is the bindings, and the arguments are swapped from $.map()
    1217         return callback.call(match.bindings, i, match.bindings, match.triples);
    1218       }));
    1219     },
    1220
    1221     /**
    1222      * Returns a {@link jQuery} object that wraps this {@link jQuery.rdf} object.
    1223      * @returns {jQuery}
    1224      */
    1225     jquery: function () {
    1226       return $(this);
    1227     }
    1228   };
    1229
    1230   $.rdf.fn.init.prototype = $.rdf.fn;
    1231
    1232   $.rdf.gleaners = [];
    1233   $.rdf.parsers = {};
    1234
    1235   /**
    1236    * Dumps the triples passed as the first argument into a format that can be shown to the user or sent to a server.
    1237    * @param {jQuery.rdf.triple[]} triples An array (or {@link jQuery} object) of {@link jQuery.rdf.triple}s.
    1238    * @param {Object} [options] Options that control the format of the dump.
    1239    * @param {String} [options.format='application/json'] The mime type of the format of the dump. The supported formats are:
    1240    * <table>
    1241    *   <tr><th>mime type</th><th>description</th></tr>
    1242    *   <tr>
    1243    *     <td><code>application/json</code></td>
    1244    *     <td>An <a href="http://n2.talis.com/wiki/RDF_JSON_Specification">RDF/JSON</a> object</td>
    1245    *   </tr>
    1246    *   <tr>
    1247    *     <td><code>application/rdf+xml</code></td>
    1248    *     <td>An DOMDocument node holding XML in <a href="http://www.w3.org/TR/rdf-syntax-grammar/">RDF/XML syntax</a></td>
    1249    *   </tr>
    1250    *   <tr>
    1251    *     <td><code>text/turtle</code></td>
    1252    *     <td>A String holding a representation of the RDF in <a href="http://www.w3.org/TeamSubmission/turtle/">Turtle syntax</a></td>
    1253    *   </tr>
    1254    * </table>
    1255    * @param {Object} [options.namespaces={}] A set of namespace bindings used when mapping resource URIs to CURIEs or QNames (particularly in a RDF/XML serialisation).
    1256    * @param {boolean} [options.serialize=false] If true, rather than creating an Object, the function will return a string which is ready to display or send to a server.
    1257    * @param {boolean} [options.indent=false] If true, the serialised (RDF/XML) output has indentation added to it to make it more readable.
    1258    * @returns {Object|String} The alternative representation of the triples.
    1259    */
    1260   $.rdf.dump = function (triples, options) {
    1261     var opts = $.extend({}, $.rdf.dump.defaults, options || {}),
    1262       format = opts.format,
    1263       serialize = opts.serialize,
    1264       dump, parser, parsers;
    1265     parser = $.rdf.parsers[format];
    1266     if (parser === undefined) {
    1267       parsers = [];
    1268       for (p in $.rdf.parsers) {
    1269         parsers.push(p);
    1270       }
    1271       throw "Unrecognised dump format: " + format + ". Expected one of " + parsers.join(", ");
    1272     }
    1273     dump = parser.dump(triples, opts);
    1274     return serialize ? parser.serialize(dump) : dump;
    1275   };
    1276
    1277   $.rdf.dump.defaults = {
    1278     format: 'application/json',
    1279     serialize: false,
    1280     indent: false,
    1281     namespaces: {}
    1282   }
    1283
    1284   /**
    1285    * Gleans RDF triples from the nodes held by the {@link jQuery} object, puts them into a {@link jQuery.rdf.databank} and returns a {@link jQuery.rdf} object that allows you to query and otherwise manipulate them. The mechanism for gleaning RDF triples from the web page depends on the rdfQuery modules that have been included. The core version of rdfQuery doesn't support any gleaners; other versions support a RDFa gleaner, and there are some modules available for common microformats.
    1286    * @methodOf jQuery#
    1287    * @name jQuery#rdf
    1288    * @param {Function} [callback] A callback function that is called every time a triple is gleaned from the page. Within the function, <code>this</code> is set to the triple that has been located. The function can take up to two parameters:
    1289    * <dl>
    1290    *   <dt>node</dt><dd>The node on which the triple has been found; should be the same as <code>this.source</code>.</dd>
    1291    *   <dt>triple</dt><dd>The triple that's been found; the same as <code>this</code>.</dd>
    1292    * </dl>
    1293    * The callback should return the triple or triples that should be added to the databank. This enables you to filter, extend or modify the contents of the databank itself, should you wish to.
    1294    * @returns {jQuery.rdf} An empty query over the triples stored within the page.
    1295    * @example $('#content').rdf().databank.dump();
    1296    */
    1297   $.fn.rdf = function (callback) {
    1298     var triples = [],
    1299       callback = callback || function () { return this; };
    1300     if ($(this)[0] && $(this)[0].nodeType === 9) {
    1301       return $(this).children('*').rdf(callback);
    1302     } else if ($(this).length > 0) {
    1303       triples = $(this).map(function (i, elem) {
    1304         return $.map($.rdf.gleaners, function (gleaner) {
    1305           return gleaner.call($(elem), { callback: callback });
    1306         });
    1307       });
    1308       return $.rdf({ triples: triples, namespaces: $(this).xmlns() });
    1309     } else {
    1310       return $.rdf();
    1311     }
    1312   };
    1313
    1314   $.extend($.expr[':'], {
    1315
    1316     about: function (a, i, m) {
    1317       var j = $(a),
    1318         resource = m[3] ? j.safeCurie(m[3]) : null,
    1319         isAbout = false;
    1320       $.each($.rdf.gleaners, function (i, gleaner) {
    1321         isAbout = gleaner.call(j, { about: resource });
    1322         if (isAbout) {
    1323           return null;
    1324         }
    1325       });
    1326       return isAbout;
    1327     },
    1328
    1329     type: function (a, i, m) {
    1330       var j = $(a),
    1331         type = m[3] ? j.curie(m[3]) : null,
    1332         isType = false;
    1333       $.each($.rdf.gleaners, function (i, gleaner) {
    1334         if (gleaner.call(j, { type: type })) {
    1335           isType = true;
    1336           return null;
    1337         }
    1338       });
    1339       return isType;
    1340     }
    1341
    1342   });
    1343
    1344   /**
    1345    * <p>Creates a new jQuery.rdf.databank object. This should be invoked as a method rather than constructed using new; indeed you will not usually want to generate these objects directly, but manipulate them through a {@link jQuery.rdf} object.</p>
    1346    * @class Represents a triplestore, holding a bunch of {@link jQuery.rdf.triple}s.
    1347    * @param {(String|jQuery.rdf.triple)[]} [triples=[]] An array of triples to store in the databank.
    1348    * @param {Object} [options] Initialisation of the databank.
    1349    * @param {Object} [options.namespaces] An object representing a set of namespace bindings used when interpreting the CURIEs in strings representing triples. Rather than passing this in when you construct the {@link jQuery.rdf.databank} instance, you will usually want to use the {@link jQuery.rdf.databank#prefix} method.
    1350    * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the strings representing triples.
    1351    * @returns {jQuery.rdf.databank} The newly-created databank.
    1352    * @see jQuery.rdf
    1353    */
    1354   $.rdf.databank = function (triples, options) {
    1355     return new $.rdf.databank.fn.init(triples, options);
    1356   };
    1357
    1358   $.rdf.databank.fn = $.rdf.databank.prototype = {
    1359     init: function (triples, options) {
    1360       var i;
    1361       triples = triples || [];
    1362       options = options || {};
    1363       this.id = databankID();
    1364       databanks[this.id] = this;
    1365       if (options.union === undefined) {
    1366         this.queries = {};
    1367         this.tripleStore = [];
    1368         this.subjectIndex = {};
    1369         this.propertyIndex = {};
    1370         this.objectIndex = {};
    1371         this.baseURI = options.base || $.uri.base();
    1372         this.namespaces = $.extend({}, options.namespaces || {});
    1373         for (i = 0; i < triples.length; i += 1) {
    1374           this.add(triples[i]);
    1375         }
    1376       } else {
    1377         this.union = options.union;
    1378       }
    1379       return this;
    1380     },
    1381
    1382     /**
    1383      * Sets or returns the base URI of the {@link jQuery.rdf.databank}.
    1384      * @param {String|jQuery.uri} [base]
    1385      * @returns A {@link jQuery.uri} if no base URI is specified, otherwise returns this {@link jQuery.rdf.databank} object.
    1386      * @see jQuery.rdf#base
    1387      */
    1388     base: function (base) {
    1389       if (this.union === undefined) {
    1390         if (base === undefined) {
    1391           return this.baseURI;
    1392         } else {
    1393           this.baseURI = base;
    1394           return this;
    1395         }
    1396       } else if (base === undefined) {
    1397         return this.union[0].base();
    1398       } else {
    1399         $.each(this.union, function (i, databank) {
    1400           databank.base(base);
    1401         });
    1402         return this;
    1403       }
    1404     },
    1405
    1406     /**
    1407      * Sets or returns a namespace binding on the {@link jQuery.rdf.databank}.
    1408      * @param {String} [prefix]
    1409      * @param {String} [namespace]
    1410      * @returns {Object|jQuery.uri|jQuery.rdf} If no prefix or namespace is specified, returns an object providing all namespace bindings on the {@link jQuery.rdf#databank}. If a prefix is specified without a namespace, returns the {@link jQuery.uri} associated with that prefix. Otherwise returns this {@link jQuery.rdf} object after setting the namespace binding.
    1411      * @see jQuery.rdf#prefix
    1412      */
    1413     prefix: function (prefix, uri) {
    1414       var namespaces = {};
    1415       if (this.union === undefined) {
    1416         if (prefix === undefined) {
    1417           return this.namespaces;
    1418         } else if (uri === undefined) {
    1419           return this.namespaces[prefix];
    1420         } else {
    1421           this.namespaces[prefix] = uri;
    1422           return this;
    1423         }
    1424       } else if (uri === undefined) {
    1425         $.each(this.union, function (i, databank) {
    1426           $.extend(namespaces, databank.prefix());
    1427         });
    1428         if (prefix === undefined) {
    1429           return namespaces;
    1430         } else {
    1431           return namespaces[prefix];
    1432         }
    1433       } else {
    1434         $.each(this.union, function (i, databank) {
    1435           databank.prefix(prefix, uri);
    1436         });
    1437         return this;
    1438       }
    1439     },
    1440
    1441     /**
    1442      * Adds a triple to the {@link jQuery.rdf.databank} or another {@link jQuery.rdf.databank} object to create a union.
    1443      * @param {String|jQuery.rdf.triple|jQuery.rdf.databank} triple The triple or {@link jQuery.rdf.databank} object to be added to this one. If the triple is a {@link jQuery.rdf.databank} object, the two databanks are unioned together. If the triple is a string, it's parsed as a {@link jQuery.rdf.triple}.
    1444      * @param {Object} [options]
    1445      * @param {Object} [options.namespaces] An object representing a set of namespace bindings used to interpret CURIEs within the triple. Defaults to the namespace bindings defined on the {@link jQuery.rdf.databank}.
    1446      * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the triple. Defaults to the base URI defined on the {@link jQuery.rdf.databank}.
    1447      * @param {Integer} [options.depth] The number of links to traverse to gather more information about the subject, property and object of the triple.
    1448      * @returns {jQuery.rdf.databank} This {@link jQuery.rdf.databank} object.
    1449      * @see jQuery.rdf#add
    1450      */
    1451     add: function (triple, options) {
    1452       var base = (options && options.base) || this.base(),
    1453         namespaces = $.extend({}, this.prefix(), (options && options.namespaces) || {}),
    1454         depth = (options && options.depth) || $.rdf.databank.defaults.depth,
    1455         proxy = (options && options.proxy) || $.rdf.databank.defaults.proxy,
    1456         databank;
    1457       if (triple === this) {
    1458         return this;
    1459       } else if (triple.subjectIndex !== undefined) {
    1460         // merging two databanks
    1461         if (this.union === undefined) {
    1462           databank = $.rdf.databank(undefined, { union: [this, triple] });
    1463           return databank;
    1464         } else {
    1465           this.union.push(triple);
    1466           return this;
    1467         }
    1468       } else {
    1469         if (typeof triple === 'string') {
    1470           triple = $.rdf.triple(triple, { namespaces: namespaces, base: base, source: triple });
    1471         }
    1472         if (this.union === undefined) {
    1473           if (this.subjectIndex[triple.subject] === undefined) {
    1474             this.subjectIndex[triple.subject] = [];
    1475             if (depth > 0 && triple.subject.type === 'uri') {
    1476               this.load(triple.subject.value, { depth: depth - 1, proxy: proxy });
    1477             }
    1478           }
    1479           if (this.propertyIndex[triple.property] === undefined) {
    1480             this.propertyIndex[triple.property] = [];
    1481             if (depth > 0) {
    1482               this.load(triple.property.value, { depth: depth - 1, proxy: proxy });
    1483             }
    1484           }
    1485           if ($.inArray(triple, this.subjectIndex[triple.subject]) === -1) {
    1486             this.tripleStore.push(triple);
    1487             this.subjectIndex[triple.subject].push(triple);
    1488             this.propertyIndex[triple.property].push(triple);
    1489             if (triple.object.type === 'uri' || triple.object.type === 'bnode') {
    1490               if (this.objectIndex[triple.object] === undefined) {
    1491                 this.objectIndex[triple.object] = [];
    1492                 if (depth > 0 && triple.object.type === 'uri') {
    1493                   this.load(triple.object.value, { depth: depth - 1, proxy: proxy });
    1494                 }
    1495               }
    1496               this.objectIndex[triple.object].push(triple);
    1497             }
    1498             addToDatabankQueries(this, triple);
    1499           }
    1500         } else {
    1501           $.each(this.union, function (i, databank) {
    1502             databank.add(triple);
    1503           });
    1504         }
    1505         return this;
    1506       }
    1507     },
    1508
    1509     /**
    1510      * Removes a triple from the {@link jQuery.rdf.databank}.
    1511      * @param {String|jQuery.rdf.triple} triple The triple to be removed.
    1512      * @param {Object} [options]
    1513      * @param {Object} [options.namespaces] An object representing a set of namespace bindings used to interpret any CURIEs within the triple. Defaults to the namespace bindings defined on the {@link jQuery.rdf.databank}.
    1514      * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the triple. Defaults to the base URI defined on the {@link jQuery.rdf.databank}.
    1515      * @returns {jQuery.rdf.databank} The {@link jQuery.rdf.databank} object itself.
    1516      * @see jQuery.rdf#remove
    1517      */
    1518     remove: function (triple, options) {
    1519       var base = (options && options.base) || this.base(),
    1520         namespaces = $.extend({}, this.prefix(), (options && options.namespaces) || {}),
    1521         striples, ptriples, otriples,
    1522         databank;
    1523       if (typeof triple === 'string') {
    1524         triple = $.rdf.triple(triple, { namespaces: namespaces, base: base, source: triple });
    1525       }
    1526       this.tripleStore.splice($.inArray(triple, this.tripleStore), 1);
    1527       striples = this.subjectIndex[triple.subject];
    1528       if (striples !== undefined) {
    1529         striples.splice($.inArray(triple, striples), 1);
    1530       }
    1531       ptriples = this.propertyIndex[triple.property];
    1532       if (ptriples !== undefined) {
    1533         ptriples.splice($.inArray(triple, ptriples), 1);
    1534       }
    1535       if (triple.object.type === 'uri' || triple.object.type === 'bnode') {
    1536         otriples = this.objectIndex[triple.object];
    1537         if (otriples !== undefined) {
    1538           otriples.splice($.inArray(triple, otriples), 1);
    1539         }
    1540       }
    1541       removeFromDatabankQueries(this, triple);
    1542       return this;
    1543     },
    1544
    1545     /**
    1546      * Creates a new databank containing all the triples in this {@link jQuery.rdf.databank} except those in the {@link jQuery.rdf.databank} passed as the argument.
    1547      * @param {jQuery.rdf.databank} data The other {@link jQuery.rdf.databank}
    1548      * @returns {jQuery.rdf.databank} A new {@link jQuery.rdf.databank} containing the triples in this {@link jQuery.rdf.databank} except for those in the data parameter.
    1549      * @example
    1550      * var old = $('html').rdf().databank;
    1551      * ...some processing occurs...
    1552      * var new = $('html').rdf().databank;
    1553      * var added = new.except(old);
    1554      * var removed = old.except(new);
    1555      */
    1556     except: function (data) {
    1557       var store = data.subjectIndex,
    1558         diff = [];
    1559       $.each(this.subjectIndex, function (s, ts) {
    1560         var ots = store[s];
    1561         if (ots === undefined) {
    1562           diff = diff.concat(ts);
    1563         } else {
    1564           $.each(ts, function (i, t) {
    1565             if ($.inArray(t, ots) === -1) {
    1566               diff.push(t);
    1567             }
    1568           });
    1569         }
    1570       });
    1571       return $.rdf.databank(diff);
    1572     },
    1573
    1574     /**
    1575      * Provides a {@link jQuery} object containing the triples held in this {@link jQuery.rdf.databank}.
    1576      * @returns {jQuery} A {@link jQuery} object containing {@link jQuery.rdf.triple} objects.
    1577      */
    1578     triples: function () {
    1579       var s, triples = [];
    1580       if (this.union === undefined) {
    1581         triples = this.tripleStore;
    1582       } else {
    1583         $.each(this.union, function (i, databank) {
    1584           triples = triples.concat(databank.triples().get());
    1585         });
    1586         triples = unique(triples);
    1587       }
    1588       return $(triples);
    1589     },
    1590
    1591     /**
    1592      * Tells you how many triples the databank contains.
    1593      * @returns {Integer} The number of triples in the {@link jQuery.rdf.databank}.
    1594      * @example $('html').rdf().databank.size();
    1595      */
    1596     size: function () {
    1597       return this.triples().length;
    1598     },
    1599
    1600     /**
    1601      * Provides <a href="http://n2.talis.com/wiki/Bounded_Descriptions_in_RDF#Simple_Concise_Bounded_Description">simple concise bounded descriptions</a> of the resources that are passed in the argument. This mirrors the <a href="http://www.w3.org/TR/rdf-sparql-query/#describe">DESCRIBE</a> form in SPARQL.
    1602      * @param {(String|jQuery.rdf.resource)[]} resources An array that can contain strings, {@link jQuery.rdf.resource}s or a mixture of the two.
    1603      * @returns {jQuery} A {@link jQuery} object holding the {@link jQuery.rdf.triple}s that describe the listed resources.
    1604      * @see jQuery.rdf#describe
    1605      */
    1606     describe: function (resources) {
    1607       var i, r, t, rhash = {}, triples = [];
    1608       while (resources.length > 0) {
    1609         r = resources.pop();
    1610         if (rhash[r] === undefined) {
    1611           if (r.value === undefined) {
    1612             r = $.rdf.resource(r);
    1613           }
    1614           if (this.subjectIndex[r] !== undefined) {
    1615             for (i = 0; i < this.subjectIndex[r].length; i += 1) {
    1616               t = this.subjectIndex[r][i];
    1617               triples.push(t);
    1618               if (t.object.type === 'bnode') {
    1619                 resources.push(t.object);
    1620               }
    1621             }
    1622           }
    1623           if (this.objectIndex[r] !== undefined) {
    1624             for (i = 0; i < this.objectIndex[r].length; i += 1) {
    1625               t = this.objectIndex[r][i];
    1626               triples.push(t);
    1627               if (t.subject.type === 'bnode') {
    1628                 resources.push(t.subject);
    1629               }
    1630             }
    1631           }
    1632           rhash[r] = true;
    1633         }
    1634       }
    1635       return unique(triples);
    1636     },
    1637
    1638     /**
    1639      * Dumps the triples in the databank into a format that can be shown to the user or sent to a server.
    1640      * @param {Object} [options] Options that control the formatting of the triples. See {@link jQuery.rdf.dump} for details.
    1641      * @returns {Object|Node|String}
    1642      * @see jQuery.rdf.dump
    1643      */
    1644     dump: function (options) {
    1645       options = $.extend({ namespaces: this.namespaces, base: this.base }, options || {});
    1646       return $.rdf.dump(this.triples(), options);
    1647     },
    1648
    1649     /**
    1650      * Loads some data into the databank.
    1651      * @param {Node|Object|String} data If the data is a string and starts with 'http://' then it's taken to be a URI and data is loaded from that URI via the proxy specified in the options. If it doesn't start with 'http://' then it's taken to be a serialized version of some format capable of representing RDF, parsed and interpreted. If the data is a node, it's interpreted to be an <a href="http://www.w3.org/TR/rdf-syntax-grammar/">RDF/XML syntax</a> document and will be parsed as such. Otherwise, it's taken to be a <a href="http://n2.talis.com/wiki/RDF_JSON_Specification">RDF/JSON</a> object.
    1652      * @param {Object} opts Options governing the loading of the data.
    1653      * @param {String} [opts.format] The mime type of the format the data is in, particularly useful if you're supplying the data as a string. If unspecified, the data will be sniffed to see if it might be HTML, RDF/XML, RDF/JSON or Turtle.
    1654      * @param {boolean} [opts.async=true] When loading data from a URI, this determines whether it will be done synchronously or asynchronously.
    1655      * @param {Function} [opts.success] When loading data from a URI, a function that will be called after the data is successfully loaded.
    1656      * @param {Function} [opts.error] When loading data from a URI, a function that will be called if there's an error when accessing the URI.
    1657      * @param {String} [opts.proxy='http://www.jenitennison.com/rdfquery/proxy.php'] The URI for a server-side proxy through which the data can be accessed. This does not have to be hosted on the same server as this Javascript, the HTML page or the remote data. The proxy must accept id, url and depth parameters and respond with some Javascript that will invoke the {@link jQuery.rdf.databank.load} function. <a href="http://code.google.com/p/rdfquery/source/browse/#svn/trunk/proxies">Example proxies</a> that do the right thing are available. If you are intending to use this facility a lot, please do not use the default proxy.
    1658      * @param {integer} [opts.depth=0] Triggers recursive loading of located resources, to the depth specified. This is useful for automatically populating a databank with linked data.
    1659      * @returns {jQuery.rdf.databank} The {@link jQuery.rdf.databank} itself.
    1660      * @see jQuery.rdf#load
    1661      */
    1662     load: function (data, opts) {
    1663       var i, triples, url, script, parser, docElem,
    1664         format = (opts && opts.format),
    1665         async = (opts && opts.async) || $.rdf.databank.defaults.async,
    1666         success = (opts && opts.success) || $.rdf.databank.defaults.success,
    1667         error = (opts && opts.error) || $.rdf.databank.defaults.error,
    1668         proxy = (opts && opts.proxy) || $.rdf.databank.defaults.proxy,
    1669         depth = (opts && opts.depth) || $.rdf.databank.defaults.depth;
    1670       url = (typeof data === 'string' && data.substring(1, 7) === 'http://') ? $.uri(data) : data;
    1671       if (url.scheme) {
    1672         if (!queue(this, url, { success: success, error: error })) {
    1673           script = '<script type="text/javascript" src="' + proxy + '?id=' + this.id + '&depth=' + depth + '&url=' + encodeURIComponent(url.resolve('').toString()) + '"></script>';
    1674           if (async) {
    1675             setTimeout("$('head').append('" + script + "')", 0);
    1676           } else {
    1677             $('head').append(script);
    1678           }
    1679         }
    1680         return this;
    1681       } else {
    1682         if (format === undefined) {
    1683           if (typeof data === 'string') {
    1684             if (data.substring(0, 1) === '{') {
    1685               format = 'application/json';
    1686             } else if (data.substring(0, 14) === '<!DOCTYPE html' || data.substring(0, 5) === '<html') {
    1687               format = 'application/xhtml+xml';
    1688             } else if (data.substring(0, 5) === '<?xml' || data.substring(0, 8) === '<rdf:RDF') {
    1689               format = 'application/rdf+xml';
    1690             } else {
    1691               format = 'text/turtle';
    1692             }
    1693           } else if (data.documentElement || data.ownerDocument) {
    1694             docElem = data.documentElement ? data.documentElement : data.ownerDocument.documentElement;
    1695             if (docElem.nodeName === 'html') {
    1696               format = 'application/xhtml+xml';
    1697             } else {
    1698               format = 'application/rdf+xml';
    1699             }
    1700           } else {
    1701             format = 'application/json';
    1702           }
    1703         }
    1704         parser = $.rdf.parsers[format];
    1705         if (typeof data === 'string') {
    1706           data = parser.parse(data);
    1707         }
    1708         triples = parser.triples(data);
    1709         for (i = 0; i < triples.length; i += 1) {
    1710           this.add(triples[i], opts);
    1711         }
    1712         return this;
    1713       }
    1714     },
    1715
    1716     /**
    1717      * Provides a string representation of the databank which simply specifies how many triples it contains.
    1718      * @returns {String}
    1719      */
    1720     toString: function () {
    1721       return '[Databank with ' + this.size() + ' triples]';
    1722     }
    1723   };
    1724
    1725   $.rdf.databank.fn.init.prototype = $.rdf.databank.fn;
    1726
    1727   $.rdf.databank.defaults = {
    1728     parse: false,
    1729     async: true,
    1730     success: null,
    1731     error: null,
    1732     depth: 0,
    1733     proxy: 'http://www.jenitennison.com/rdfquery/proxy.php'
    1734   };
    1735
    1736   $.rdf.databank.load = function (id, url, doc, opts) {
    1737     if (doc !== undefined) {
    1738       databanks[id].load(doc, opts);
    1739     }
    1740     dequeue(databanks[id], url, (doc === undefined) ? 'error' : 'success', opts);
    1741   };
    1742
    1743   /**
    1744    * <p>Creates a new jQuery.rdf.pattern object. This should be invoked as a method rather than constructed using new; indeed you will not usually want to generate these objects directly, since they are automatically created from strings where necessary, such as by {@link jQuery.rdf#where}.</p>
    1745    * @class Represents a pattern that may or may not match a given {@link jQuery.rdf.triple}.
    1746    * @param {String|jQuery.rdf.resource|jQuery.rdf.blank} subject The subject pattern, or a single string that defines the entire pattern. If the subject is specified as a string, it can be a fixed resource (<code><<var>uri</var>></code> or <code><var>curie</var></code>), a blank node (<code>_:<var>id</var></code>) or a variable placeholder (<code>?<var>name</var></code>).
    1747    * @param {String|jQuery.rdf.resource} [property] The property pattern. If the property is specified as a string, it can be a fixed resource (<code><<var>uri</var>></code> or <code><var>curie</var></code>) or a variable placeholder (<code>?<var>name</var></code>).
    1748    * @param {String|jQuery.rdf.resource|jQuery.rdf.blank|jQuery.rdf.literal} [value] The value pattern. If the property is specified as a string, it can be a fixed resource (<code><<var>uri</var>></code> or <code><var>curie</var></code>), a blank node (<code>_:<var>id</var></code>), a literal (<code>"<var>value</var>"</code>) or a variable placeholder (<code>?<var>name</var></code>).
    1749    * @param {Object} [options] Initialisation of the pattern.
    1750    * @param {Object} [options.namespaces] An object representing a set of namespace bindings used when interpreting the CURIEs in the subject, property and object.
    1751    * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the subject, property and object.
    1752    * @param {boolean} [options.optional]
    1753    * @returns {jQuery.rdf.pattern} The newly-created pattern.
    1754    * @throws {String} Errors if any of the strings are not in a recognised format.
    1755    * @example pattern = $.rdf.pattern('?person', $.rdf.type, 'foaf:Person', { namespaces: { foaf: "http://xmlns.com/foaf/0.1/" }});
    1756    * @example
    1757    * pattern = $.rdf.pattern('?person a foaf:Person', {
    1758    *   namespaces: { foaf: "http://xmlns.com/foaf/0.1/" },
    1759    *   optional: true
    1760    * });
    1761    * @see jQuery.rdf#where
    1762    * @see jQuery.rdf.resource
    1763    * @see jQuery.rdf.blank
    1764    * @see jQuery.rdf.literal
    1765    */
    1766   $.rdf.pattern = function (subject, property, object, options) {
    1767     var pattern, m, optional;
    1768     // using a two-argument version; first argument is a Turtle statement string
    1769     if (object === undefined) {
    1770       options = property || {};
    1771       m = $.trim(subject).match(tripleRegex);
    1772       if (m.length === 3 || (m.length === 4 && m[3] === '.')) {
    1773         subject = m[0];
    1774         property = m[1];
    1775         object = m[2];
    1776       } else {
    1777         throw "Bad Pattern: Couldn't parse string " + subject;
    1778       }
    1779       optional = (options.optional === undefined) ? $.rdf.pattern.defaults.optional : options.optional;
    1780     }
    1781     if (memPattern[subject] &&
    1782         memPattern[subject][property] &&
    1783         memPattern[subject][property][object] &&
    1784         memPattern[subject][property][object][optional]) {
    1785       return memPattern[subject][property][object][optional];
    1786     }
    1787     pattern = new $.rdf.pattern.fn.init(subject, property, object, options);
    1788     if (memPattern[pattern.subject] &&
    1789         memPattern[pattern.subject][pattern.property] &&
    1790         memPattern[pattern.subject][pattern.property][pattern.object] &&
    1791         memPattern[pattern.subject][pattern.property][pattern.object][pattern.optional]) {
    1792       return memPattern[pattern.subject][pattern.property][pattern.object][pattern.optional];
    1793     } else {
    1794       if (memPattern[pattern.subject] === undefined) {
    1795         memPattern[pattern.subject] = {};
    1796       }
    1797       if (memPattern[pattern.subject][pattern.property] === undefined) {
    1798         memPattern[pattern.subject][pattern.property] = {};
    1799       }
    1800       if (memPattern[pattern.subject][pattern.property][pattern.object] === undefined) {
    1801         memPattern[pattern.subject][pattern.property][pattern.object] = {};
    1802       }
    1803       memPattern[pattern.subject][pattern.property][pattern.object][pattern.optional] = pattern;
    1804       return pattern;
    1805     }
    1806   };
    1807
    1808   $.rdf.pattern.fn = $.rdf.pattern.prototype = {
    1809     init: function (s, p, o, options) {
    1810       var opts = $.extend({}, $.rdf.pattern.defaults, options);
    1811       /**
    1812        * The placeholder for the subject of triples matching against this pattern.
    1813        * @type String|jQuery.rdf.resource|jQuery.rdf.blank
    1814        */
    1815       this.subject = s.toString().substring(0, 1) === '?' ? s : subject(s, opts);
    1816       /**
    1817        * The placeholder for the property of triples matching against this pattern.
    1818        * @type String|jQuery.rdf.resource
    1819        */
    1820       this.property = p.toString().substring(0, 1) === '?' ? p : property(p, opts);
    1821       /**
    1822        * The placeholder for the object of triples matching against this pattern.
    1823        * @type String|jQuery.rdf.resource|jQuery.rdf.blank|jQuery.rdf.literal
    1824        */
    1825       this.object = o.toString().substring(0, 1) === '?' ? o : object(o, opts);
    1826       /**
    1827        * Whether the pattern should only optionally match against the triple
    1828        * @type boolean
    1829        */
    1830       this.optional = opts.optional;
    1831       return this;
    1832     },
    1833
    1834     /**
    1835      * Creates a new {@link jQuery.rdf.pattern} with any variable placeholders within this one's subject, property or object filled in with values from the bindings passed as the argument.
    1836      * @param {Object} bindings An object holding the variable bindings to be used to replace any placeholders in the pattern. These bindings are of the type held by the {@link jQuery.rdf} object.
    1837      * @returns {jQuery.rdf.pattern} A new {@link jQuery.rdf.pattern} object.
    1838      * @example
    1839      * pattern = $.rdf.pattern('?thing a ?class');
    1840      * // pattern2 matches all triples that indicate the classes of this page.
    1841      * pattern2 = pattern.fill({ thing: $.rdf.resource('<>') });
    1842      */
    1843     fill: function (bindings) {
    1844       var s = this.subject,
    1845         p = this.property,
    1846         o = this.object;
    1847       if (typeof s === 'string' && bindings[s.substring(1)]) {
    1848         s = bindings[s.substring(1)];
    1849       }
    1850       if (typeof p === 'string' && bindings[p.substring(1)]) {
    1851         p = bindings[p.substring(1)];
    1852       }
    1853       if (typeof o === 'string' && bindings[o.substring(1)]) {
    1854         o = bindings[o.substring(1)];
    1855       }
    1856       return $.rdf.pattern(s, p, o, { optional: this.optional });
    1857     },
    1858
    1859     /**
    1860      * Creates a new Object holding variable bindings by matching the passed triple against this pattern.
    1861      * @param {jQuery.rdf.triple} triple A {@link jQuery.rdf.triple} for this pattern to match against.
    1862      * @returns {null|Object} An object containing the bindings of variables (as specified in this pattern) to values (as specified in the triple), or <code>null</code> if the triple doesn't match the pattern.
    1863      * pattern = $.rdf.pattern('?thing a ?class');
    1864      * bindings = pattern.exec($.rdf.triple('<> a foaf:Person', { namespaces: ns }));
    1865      * thing = bindings.thing; // the resource for this page
    1866      * class = bindings.class; // a resource for foaf:Person
    1867      */
    1868     exec: function (triple) {
    1869       var binding = {};
    1870       binding = testResource(triple.subject, this.subject, binding);
    1871       if (binding === null) {
    1872         return null;
    1873       }
    1874       binding = testResource(triple.property, this.property, binding);
    1875       if (binding === null) {
    1876         return null;
    1877       }
    1878       binding = testResource(triple.object, this.object, binding);
    1879       return binding;
    1880     },
    1881
    1882     /**
    1883      * Tests whether this pattern has any variable placeholders in it or not.
    1884      * @returns {boolean} True if the pattern doesn't contain any variable placeholders.
    1885      * @example
    1886      * $.rdf.pattern('?thing a ?class').isFixed(); // false
    1887      * $.rdf.pattern('<> a foaf:Person', { namespaces: ns }).isFixed(); // true
    1888      */
    1889     isFixed: function () {
    1890       return typeof this.subject !== 'string' &&
    1891         typeof this.property !== 'string' &&
    1892         typeof this.object !== 'string';
    1893     },
    1894
    1895     /**
    1896      * Creates a new triple based on the bindings passed to the pattern, if possible.
    1897      * @param {Object} bindings An object holding the variable bindings to be used to replace any placeholders in the pattern. These bindings are of the type held by the {@link jQuery.rdf} object.
    1898      * @returns {null|jQuery.rdf.triple} A new {@link jQuery.rdf.triple} object, or null if not all the variable placeholders in the pattern are specified in the bindings. The {@link jQuery.rdf.triple#source} of the generated triple is set to the string value of this pattern.
    1899      * @example
    1900      * pattern = $.rdf.pattern('?thing a ?class');
    1901      * // triple is a new triple '<> a foaf:Person'
    1902      * triple = pattern.triple({
    1903      *   thing: $.rdf.resource('<>'),
    1904      *   class: $.rdf.resource('foaf:Person', { namespaces: ns })
    1905      * });
    1906      */
    1907     triple: function (bindings) {
    1908       var t = this;
    1909       if (!this.isFixed()) {
    1910         t = this.fill(bindings);
    1911       }
    1912       if (t.isFixed()) {
    1913         return $.rdf.triple(t.subject, t.property, t.object, { source: this.toString() });
    1914       } else {
    1915         return null;
    1916       }
    1917     },
    1918
    1919     /**
    1920      * Returns a string representation of the pattern by concatenating the subject, property and object.
    1921      * @returns {String}
    1922      */
    1923     toString: function () {
    1924       return this.subject + ' ' + this.property + ' ' + this.object;
    1925     }
    1926   };
    1927
    1928   $.rdf.pattern.fn.init.prototype = $.rdf.pattern.fn;
    1929
    1930   $.rdf.pattern.defaults = {
    1931     base: $.uri.base(),
    1932     namespaces: {},
    1933     optional: false
    1934   };
    1935
    1936   /**
    1937    * <p>Creates a new jQuery.rdf.triple object. This should be invoked as a method rather than constructed using new; indeed you will not usually want to generate these objects directly, since they are automatically created from strings where necessary, such as by {@link jQuery.rdf#add}.</p>
    1938    * @class Represents an RDF triple.
    1939    * @param {String|jQuery.rdf.resource|jQuery.rdf.blank} subject The subject of the triple, or a single string that defines the entire triple. If the subject is specified as a string, it can be a fixed resource (<code><<var>uri</var>></code> or <code><var>curie</var></code>) or a blank node (<code>_:<var>id</var></code>).
    1940    * @param {String|jQuery.rdf.resource} [property] The property pattern. If the property is specified as a string, it must be a fixed resource (<code><<var>uri</var>></code> or <code><var>curie</var></code>).
    1941    * @param {String|jQuery.rdf.resource|jQuery.rdf.blank|jQuery.rdf.literal} [value] The value pattern. If the property is specified as a string, it can be a fixed resource (<code><<var>uri</var>></code> or <code><var>curie</var></code>), a blank node (<code>_:<var>id</var></code>), or a literal (<code>"<var>value</var>"</code>).
    1942    * @param {Object} [options] Initialisation of the triple.
    1943    * @param {Object} [options.namespaces] An object representing a set of namespace bindings used when interpreting the CURIEs in the subject, property and object.
    1944    * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the subject, property and object.
    1945    * @returns {jQuery.rdf.triple} The newly-created triple.
    1946    * @throws {String} Errors if any of the strings are not in a recognised format.
    1947    * @example pattern = $.rdf.triple('<>', $.rdf.type, 'foaf:Person', { namespaces: { foaf: "http://xmlns.com/foaf/0.1/" }});
    1948    * @example
    1949    * pattern = $.rdf.triple('<> a foaf:Person', {
    1950    *   namespaces: { foaf: "http://xmlns.com/foaf/0.1/" }
    1951    * });
    1952    * @see jQuery.rdf#add
    1953    * @see jQuery.rdf.resource
    1954    * @see jQuery.rdf.blank
    1955    * @see jQuery.rdf.literal
    1956    */
    1957   $.rdf.triple = function (subject, property, object, options) {
    1958     var triple, graph, m;
    1959     // using a two-argument version; first argument is a Turtle statement string
    1960     if (object === undefined) {
    1961       options = property;
    1962       m = $.trim(subject).match(tripleRegex);
    1963       if (m.length === 3 || (m.length === 4 && m[3] === '.')) {
    1964         subject = m[0];
    1965         property = m[1];
    1966         object = m[2];
    1967       } else {
    1968         throw "Bad Triple: Couldn't parse string " + subject;
    1969       }
    1970     }
    1971     graph = (options && options.graph) || '';
    1972     if (memTriple[graph] &&
    1973         memTriple[graph][subject] &&
    1974         memTriple[graph][subject][property] &&
    1975         memTriple[graph][subject][property][object]) {
    1976       return memTriple[graph][subject][property][object];
    1977     }
    1978     triple = new $.rdf.triple.fn.init(subject, property, object, options);
    1979     graph = triple.graph || '';
    1980     if (memTriple[graph] &&
    1981         memTriple[graph][triple.subject] &&
    1982         memTriple[graph][triple.subject][triple.property] &&
    1983         memTriple[graph][triple.subject][triple.property][triple.object]) {
    1984       return memTriple[graph][triple.subject][triple.property][triple.object];
    1985     } else {
    1986       if (memTriple[graph] === undefined) {
    1987         memTriple[graph] = {};
    1988       }
    1989       if (memTriple[graph][triple.subject] === undefined) {
    1990         memTriple[graph][triple.subject] = {};
    1991       }
    1992       if (memTriple[graph][triple.subject][triple.property] === undefined) {
    1993         memTriple[graph][triple.subject][triple.property] = {};
    1994       }
    1995       memTriple[graph][triple.subject][triple.property][triple.object] = triple;
    1996       return triple;
    1997     }
    1998   };
    1999
    2000   $.rdf.triple.fn = $.rdf.triple.prototype = {
    2001     init: function (s, p, o, options) {
    2002       var opts;
    2003       opts = $.extend({}, $.rdf.triple.defaults, options);
    2004       /**
    2005        * The subject of the triple.
    2006        * @type jQuery.rdf.resource|jQuery.rdf.blank
    2007        */
    2008       this.subject = subject(s, opts);
    2009       /**
    2010        * The property of the triple.
    2011        * @type jQuery.rdf.resource
    2012        */
    2013       this.property = property(p, opts);
    2014       /**
    2015        * The object of the triple.
    2016        * @type jQuery.rdf.resource|jQuery.rdf.blank|jQuery.rdf.literal
    2017        */
    2018       this.object = object(o, opts);
    2019       /**
    2020        * (Experimental) The named graph the triple belongs to.
    2021        * @type jQuery.rdf.resource|jQuery.rdf.blank
    2022        */
    2023       this.graph = opts.graph === undefined ? undefined : subject(opts.graph, opts);
    2024       /**
    2025        * The source of the triple, which might be a node within the page (if the RDF is generated from the page) or a string holding the pattern that generated the triple.
    2026        */
    2027       this.source = opts.source;
    2028       return this;
    2029     },
    2030
    2031     /**
    2032      * Always returns true for triples.
    2033      * @see jQuery.rdf.pattern#isFixed
    2034      */
    2035     isFixed: function () {
    2036       return true;
    2037     },
    2038
    2039     /**
    2040      * Always returns this triple.
    2041      * @see jQuery.rdf.pattern#triple
    2042      */
    2043     triple: function (bindings) {
    2044       return this;
    2045     },
    2046
    2047     /**
    2048      * Returns a <a href="http://n2.talis.com/wiki/RDF_JSON_Specification">RDF/JSON</a> representation of this triple.
    2049      * @returns {Object}
    2050      */
    2051     dump: function () {
    2052       var e = {},
    2053         s = this.subject.value.toString(),
    2054         p = this.property.value.toString();
    2055       e[s] = {};
    2056       e[s][p] = this.object.dump();
    2057       return e;
    2058     },
    2059
    2060     /**
    2061      * Returns a string representing this triple in Turtle format.
    2062      * @returns {String}
    2063      */
    2064     toString: function () {
    2065       return this.subject + ' ' + this.property + ' ' + this.object + ' .';
    2066     }
    2067   };
    2068
    2069   $.rdf.triple.fn.init.prototype = $.rdf.triple.fn;
    2070
    2071   $.rdf.triple.defaults = {
    2072     base: $.uri.base(),
    2073     source: [document],
    2074     namespaces: {}
    2075   };
    2076
    2077   /**
    2078    * <p>Creates a new jQuery.rdf.resource object. This should be invoked as a method rather than constructed using new; indeed you will not usually want to generate these objects directly, since they are automatically created from strings where necessary, such as by {@link jQuery.rdf#add}.</p>
    2079    * @class Represents an RDF resource.
    2080    * @param {String|jQuery.uri} value The value of the resource. If it's a string it must be in the format <code><<var>uri</var>></code> or <code><var>curie</var></code>.
    2081    * @param {Object} [options] Initialisation of the resource.
    2082    * @param {Object} [options.namespaces] An object representing a set of namespace bindings used when interpreting the CURIE specifying the resource.
    2083    * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the URI specifying the resource.
    2084    * @returns {jQuery.rdf.resource} The newly-created resource.
    2085    * @throws {String} Errors if the string is not in a recognised format.
    2086    * @example thisPage = $.rdf.resource('<>');
    2087    * @example foaf.Person = $.rdf.resource('foaf:Person', { namespaces: ns });
    2088    * @see jQuery.rdf.pattern
    2089    * @see jQuery.rdf.triple
    2090    * @see jQuery.rdf.blank
    2091    * @see jQuery.rdf.literal
    2092    */
    2093   $.rdf.resource = function (value, options) {
    2094     var resource;
    2095     if (memResource[value]) {
    2096       return memResource[value];
    2097     }
    2098     resource = new $.rdf.resource.fn.init(value, options);
    2099     if (memResource[resource]) {
    2100       return memResource[resource];
    2101     } else {
    2102       memResource[resource] = resource;
    2103       return resource;
    2104     }
    2105   };
    2106
    2107   $.rdf.resource.fn = $.rdf.resource.prototype = {
    2108     /**
    2109      * Always fixed to 'uri' for resources.
    2110      * @type String
    2111      */
    2112     type: 'uri',
    2113     /**
    2114      * The URI for the resource.
    2115      * @type jQuery.rdf.uri
    2116      */
    2117     value: undefined,
    2118
    2119     init: function (value, options) {
    2120       var m, prefix, uri, opts;
    2121       if (typeof value === 'string') {
    2122         m = uriRegex.exec(value);
    2123         opts = $.extend({}, $.rdf.resource.defaults, options);
    2124         if (m !== null) {
    2125           this.value = $.uri.resolve(m[1].replace(/\\>/g, '>'), opts.base);
    2126         } else if (value.substring(0, 1) === ':') {
    2127           uri = opts.namespaces[''];
    2128           if (uri === undefined) {
    2129             throw "Malformed Resource: No namespace binding for default namespace in " + value;
    2130           } else {
    2131             this.value = $.uri.resolve(uri + value.substring(1));
    2132           }
    2133         } else if (value.substring(value.length - 1) === ':') {
    2134           prefix = value.substring(0, value.length - 1);
    2135           uri = opts.namespaces[prefix];
    2136           if (uri === undefined) {
    2137             throw "Malformed Resource: No namespace binding for prefix " + prefix + " in " + value;
    2138           } else {
    2139             this.value = $.uri.resolve(uri);
    2140           }
    2141         } else {
    2142           try {
    2143             this.value = $.curie(value, { namespaces: opts.namespaces });
    2144           } catch (e) {
    2145             throw "Malformed Resource: Bad format for resource " + e;
    2146           }
    2147         }
    2148       } else {
    2149         this.value = value;
    2150       }
    2151       return this;
    2152     }, // end init
    2153
    2154     /**
    2155      * Returns a <a href="http://n2.talis.com/wiki/RDF_JSON_Specification">RDF/JSON</a> representation of this triple.
    2156      * @returns {Object}
    2157      */
    2158     dump: function () {
    2159       return {
    2160         type: 'uri',
    2161         value: this.value.toString()
    2162       };
    2163     },
    2164
    2165     /**
    2166      * Returns a string representing this resource in Turtle format.
    2167      * @returns {String}
    2168      */
    2169     toString: function () {
    2170       return '<' + this.value + '>';
    2171     }
    2172   };
    2173
    2174   $.rdf.resource.fn.init.prototype = $.rdf.resource.fn;
    2175
    2176   $.rdf.resource.defaults = {
    2177     base: $.uri.base(),
    2178     namespaces: {}
    2179   };
    2180
    2181   /**
    2182    * A {@link jQuery.rdf.resource} for rdf:type
    2183    * @constant
    2184    * @type jQuery.rdf.resource
    2185    */
    2186   $.rdf.type = $.rdf.resource('<' + rdfNs + 'type>');
    2187   /**
    2188    * A {@link jQuery.rdf.resource} for rdfs:label
    2189    * @constant
    2190    * @type jQuery.rdf.resource
    2191    */
    2192   $.rdf.label = $.rdf.resource('<' + rdfsNs + 'label>');
    2193   /**
    2194    * A {@link jQuery.rdf.resource} for rdf:first
    2195    * @constant
    2196    * @type jQuery.rdf.resource
    2197    */
    2198   $.rdf.first = $.rdf.resource('<' + rdfNs + 'first>');
    2199   /**
    2200    * A {@link jQuery.rdf.resource} for rdf:rest
    2201    * @constant
    2202    * @type jQuery.rdf.resource
    2203    */
    2204   $.rdf.rest = $.rdf.resource('<' + rdfNs + 'rest>');
    2205   /**
    2206    * A {@link jQuery.rdf.resource} for rdf:nil
    2207    * @constant
    2208    * @type jQuery.rdf.resource
    2209    */
    2210   $.rdf.nil = $.rdf.resource('<' + rdfNs + 'nil>');
    2211   /**
    2212    * A {@link jQuery.rdf.resource} for rdf:subject
    2213    * @constant
    2214    * @type jQuery.rdf.resource
    2215    */
    2216   $.rdf.subject = $.rdf.resource('<' + rdfNs + 'subject>');
    2217   /**
    2218    * A {@link jQuery.rdf.resource} for rdf:property
    2219    * @constant
    2220    * @type jQuery.rdf.resource
    2221    */
    2222   $.rdf.property = $.rdf.resource('<' + rdfNs + 'property>');
    2223   /**
    2224    * A {@link jQuery.rdf.resource} for rdf:object
    2225    * @constant
    2226    * @type jQuery.rdf.resource
    2227    */
    2228   $.rdf.object = $.rdf.resource('<' + rdfNs + 'object>');
    2229
    2230   /**
    2231    * <p>Creates a new jQuery.rdf.blank object. This should be invoked as a method rather than constructed using new; indeed you will not usually want to generate these objects directly, since they are automatically created from strings where necessary, such as by {@link jQuery.rdf#add}.</p>
    2232    * @class Represents an RDF blank node.
    2233    * @param {String} value A representation of the blank node in the format <code>_:<var>id</var></code> or <code>[]</code> (which automatically creates a new blank node with a unique ID).
    2234    * @returns {jQuery.rdf.blank} The newly-created blank node.
    2235    * @throws {String} Errors if the string is not in a recognised format.
    2236    * @example newBlank = $.rdf.blank('[]');
    2237    * @example identifiedBlank = $.rdf.blank('_:fred');
    2238    * @see jQuery.rdf.pattern
    2239    * @see jQuery.rdf.triple
    2240    * @see jQuery.rdf.resource
    2241    * @see jQuery.rdf.literal
    2242    */
    2243   $.rdf.blank = function (value) {
    2244     var blank;
    2245     if (memBlank[value]) {
    2246       return memBlank[value];
    2247     }
    2248     blank = new $.rdf.blank.fn.init(value);
    2249     if (memBlank[blank]) {
    2250       return memBlank[blank];
    2251     } else {
    2252       memBlank[blank] = blank;
    2253       return blank;
    2254     }
    2255   };
    2256
    2257   $.rdf.blank.fn = $.rdf.blank.prototype = {
    2258     /**
    2259      * Always fixed to 'bnode' for blank nodes.
    2260      * @type String
    2261      */
    2262     type: 'bnode',
    2263     /**
    2264      * The value of the blank node in the format <code>_:<var>id</var></code>
    2265      * @type String
    2266      */
    2267     value: undefined,
    2268     /**
    2269      * The id of the blank node.
    2270      * @type String
    2271      */
    2272     id: undefined,
    2273
    2274     init: function (value) {
    2275       if (value === '[]') {
    2276         this.id = blankNodeID();
    2277         this.value = '_:' + this.id;
    2278       } else if (value.substring(0, 2) === '_:') {
    2279         this.id = value.substring(2);
    2280         this.value = value;
    2281       } else {
    2282         throw "Malformed Blank Node: " + value + " is not a legal format for a blank node";
    2283       }
    2284       return this;
    2285     },
    2286
    2287     /**
    2288      * Returns a <a href="http://n2.talis.com/wiki/RDF_JSON_Specification">RDF/JSON</a> representation of this blank node.
    2289      * @returns {Object}
    2290      */
    2291     dump: function () {
    2292       return {
    2293         type: 'bnode',
    2294         value: this.value
    2295       };
    2296     },
    2297
    2298     /**
    2299      * Returns the value this blank node.
    2300      * @returns {String}
    2301      */
    2302     toString: function () {
    2303       return this.value;
    2304     }
    2305   };
    2306
    2307   $.rdf.blank.fn.init.prototype = $.rdf.blank.fn;
    2308
    2309   /**
    2310    * <p>Creates a new jQuery.rdf.literal object. This should be invoked as a method rather than constructed using new; indeed you will not usually want to generate these objects directly, since they are automatically created from strings where necessary, such as by {@link jQuery.rdf#add}.</p>
    2311    * @class Represents an RDF literal.
    2312    * @param {String|boolean|Number} value Either the value of the literal or a string representation of it. If the datatype or lang options are specified, the value is taken as given. Otherwise, if it's a Javascript boolean or numeric value, it is interpreted as a value with a xsd:boolean or xsd:double datatype. In all other cases it's interpreted as a literal as defined in <a href="http://www.w3.org/TeamSubmission/turtle/#literal">Turtle syntax</a>.
    2313    * @param {Object} [options] Initialisation options for the literal.
    2314    * @param {String} [options.datatype] The datatype for the literal. This should be a safe CURIE; in other words, it can be in the format <code><var>uri</var></code> or <code>[<var>curie</var>]</code>. Must not be specified if options.lang is also specified.
    2315    * @param {String} [options.lang] The language for the literal. Must not be specified if options.datatype is also specified.
    2316    * @param {Object} [options.namespaces] An object representing a set of namespace bindings used when interpreting a CURIE in the datatype.
    2317    * @param {String|jQuery.uri} [options.base] The base URI used to interpret a relative URI in the datatype.
    2318    * @returns {jQuery.rdf.literal} The newly-created literal.
    2319    * @throws {String} Errors if the string is not in a recognised format or if both options.datatype and options.lang are specified.
    2320    * @example trueLiteral = $.rdf.literal(true);
    2321    * @example numericLiteral = $.rdf.literal(5);
    2322    * @example dateLiteral = $.rdf.literal('"2009-07-13"^^xsd:date', { namespaces: ns });
    2323    * @see jQuery.rdf.pattern
    2324    * @see jQuery.rdf.triple
    2325    * @see jQuery.rdf.resource
    2326    * @see jQuery.rdf.blank
    2327    */
    2328   $.rdf.literal = function (value, options) {
    2329     var literal;
    2330     if (memLiteral[value]) {
    2331       return memLiteral[value];
    2332     }
    2333     literal = new $.rdf.literal.fn.init(value, options);
    2334     if (memLiteral[literal]) {
    2335       return memLiteral[literal];
    2336     } else {
    2337       memLiteral[literal] = literal;
    2338       return literal;
    2339     }
    2340   };
    2341
    2342   $.rdf.literal.fn = $.rdf.literal.prototype = {
    2343     /**
    2344      * Always fixed to 'literal' for literals.
    2345      * @type String
    2346      */
    2347     type: 'literal',
    2348     /**
    2349      * The value of the literal as a string.
    2350      * @type String
    2351      */
    2352     value: undefined,
    2353     /**
    2354      * The language of the literal, if it has one; otherwise undefined.
    2355      * @type String
    2356      */
    2357     lang: undefined,
    2358     /**
    2359      * The datatype of the literal, if it has one; otherwise undefined.
    2360      * @type jQuery.uri
    2361      */
    2362     datatype: undefined,
    2363
    2364     init: function (value, options) {
    2365       var
    2366         m, datatype,
    2367         opts = $.extend({}, $.rdf.literal.defaults, options);
    2368       datatype = $.safeCurie(opts.datatype, { namespaces: opts.namespaces });
    2369       if (opts.lang !== undefined && opts.datatype !== undefined && datatype.toString() !== (rdfNs + 'XMLLiteral')) {
    2370         throw "Malformed Literal: Cannot define both a language and a datatype for a literal (" + value + ")";
    2371       }
    2372       if (opts.datatype !== undefined) {
    2373         datatype = $.safeCurie(opts.datatype, { namespaces: opts.namespaces });
    2374         $.extend(this, $.typedValue(value.toString(), datatype));
    2375         if (datatype.toString() === rdfNs + 'XMLLiteral') {
    2376           this.lang = opts.lang;
    2377         }
    2378       } else if (opts.lang !== undefined) {
    2379         this.value = value.toString();
    2380         this.lang = opts.lang;
    2381       } else if (typeof value === 'boolean') {
    2382         $.extend(this, $.typedValue(value.toString(), xsdNs + 'boolean'));
    2383       } else if (typeof value === 'number') {
    2384         $.extend(this, $.typedValue(value.toString(), xsdNs + 'double'));
    2385       } else if (value === 'true' || value === 'false') {
    2386         $.extend(this, $.typedValue(value, xsdNs + 'boolean'));
    2387       } else if ($.typedValue.valid(value, xsdNs + 'integer')) {
    2388         $.extend(this, $.typedValue(value, xsdNs + 'integer'));
    2389       } else if ($.typedValue.valid(value, xsdNs + 'decimal')) {
    2390         $.extend(this, $.typedValue(value, xsdNs + 'decimal'));
    2391       } else if ($.typedValue.valid(value, xsdNs + 'double') &&
    2392                  !/^\s*([\-\+]?INF|NaN)\s*$/.test(value)) {  // INF, -INF and NaN aren't valid literals in Turtle
    2393         $.extend(this, $.typedValue(value, xsdNs + 'double'));
    2394       } else {
    2395         m = literalRegex.exec(value);
    2396         if (m !== null) {
    2397           this.value = (m[2] || m[4]).replace(/\\"/g, '"').replace(/\\n/g, '\n').replace(/\\t/g, '\t').replace(/\\r/g, '\r');
    2398           if (m[9]) {
    2399             datatype = $.rdf.resource(m[9], opts);
    2400             $.extend(this, $.typedValue(this.value, datatype.value));
    2401           } else if (m[7]) {
    2402             this.lang = m[7];
    2403           }
    2404         } else {
    2405           throw "Malformed Literal: Couldn't recognise the value " + value;
    2406         }
    2407       }
    2408       return this;
    2409     }, // end init
    2410
    2411     /**
    2412      * Returns a <a href="http://n2.talis.com/wiki/RDF_JSON_Specification">RDF/JSON</a> representation of this blank node.
    2413      * @returns {Object}
    2414      */
    2415     dump: function () {
    2416       var e = {
    2417         type: 'literal',
    2418         value: this.value.toString()
    2419       };
    2420       if (this.lang !== undefined) {
    2421         e.lang = this.lang;
    2422       } else if (this.datatype !== undefined) {
    2423         e.datatype = this.datatype.toString();
    2424       }
    2425       return e;
    2426     },
    2427
    2428     /**
    2429      * Returns a string representing this resource in <a href="http://www.w3.org/TeamSubmission/turtle/#literal">Turtle format</a>.
    2430      * @returns {String}
    2431      */
    2432     toString: function () {
    2433       var val = '"' + this.value + '"';
    2434       if (this.lang !== undefined) {
    2435         val += '@' + this.lang;
    2436       } else if (this.datatype !== undefined) {
    2437         val += '^^<' + this.datatype + '>';
    2438       }
    2439       return val;
    2440     }
    2441   };
    2442
    2443   $.rdf.literal.fn.init.prototype = $.rdf.literal.fn;
    2444
    2445   $.rdf.literal.defaults = {
    2446     base: $.uri.base(),
    2447     namespaces: {},
    2448     datatype: undefined,
    2449     lang: undefined
    2450   };
    2451
    2452 })(jQuery);
    2453