/* * $ URIs @VERSION * * Copyright (c) 2008,2009 Jeni Tennison * Licensed under the MIT (MIT-LICENSE.txt) * */ /** * @fileOverview $ URIs * @author Jeni Tennison * @copyright (c) 2008,2009 Jeni Tennison * @license MIT license (MIT-LICENSE.txt) * @version 1.0 */ /** * @class * @name jQuery * @exports $ as jQuery * @description rdfQuery is a jQuery plugin. The only fields and methods listed here are those that come as part of the rdfQuery library. */ (function ($) { var mem = {}, uriRegex = /^(([a-z][\-a-z0-9+\.]*):)?(\/\/([^\/?#]+))?([^?#]*)?(\?([^#]*))?(#(.*))?$/i, docURI, parseURI = function (u) { var m = u.match(uriRegex); if (m === null) { throw "Malformed URI: " + u; } return { scheme: m[1] ? m[2].toLowerCase() : undefined, authority: m[3] ? m[4] : undefined, path: m[5] || '', query: m[6] ? m[7] : undefined, fragment: m[8] ? m[9] : undefined }; }, removeDotSegments = function (u) { var r = '', m = []; if (/\./.test(u)) { while (u !== undefined && u !== '') { if (u === '.' || u === '..') { u = ''; } else if (/^\.\.\//.test(u)) { // starts with ../ u = u.substring(3); } else if (/^\.\//.test(u)) { // starts with ./ u = u.substring(2); } else if (/^\/\.(\/|$)/.test(u)) { // starts with /./ or consists of /. u = '/' + u.substring(3); } else if (/^\/\.\.(\/|$)/.test(u)) { // starts with /../ or consists of /.. u = '/' + u.substring(4); r = r.replace(/\/?[^\/]+$/, ''); } else { m = u.match(/^(\/?[^\/]*)(\/.*)?$/); u = m[2]; r = r + m[1]; } } return r; } else { return u; } }, merge = function (b, r) { if (b.authority !== '' && (b.path === undefined || b.path === '')) { return '/' + r; } else { return b.path.replace(/[^\/]+$/, '') + r; } }; /** * Creates a new jQuery.uri object. This should be invoked as a method rather than constructed using new. * @class Represents a URI * @param {String} [relative=''] * @param {String|jQuery.uri} [base] Defaults to the base URI of the page * @returns {jQuery.uri} The new jQuery.uri object. * @example uri = jQuery.uri('/my/file.html'); */ $.uri = function (relative, base) { var uri; relative = relative || ''; if (mem[relative]) { return mem[relative]; } base = base || $.uri.base(); if (typeof base === 'string') { base = $.uri.absolute(base); } uri = new $.uri.fn.init(relative, base); if (mem[uri]) { return mem[uri]; } else { mem[uri] = uri; return uri; } }; $.uri.fn = $.uri.prototype = { /** * The scheme used in the URI * @type String */ scheme: undefined, /** * The authority used in the URI * @type String */ authority: undefined, /** * The path used in the URI * @type String */ path: undefined, /** * The query part of the URI * @type String */ query: undefined, /** * The fragment part of the URI * @type String */ fragment: undefined, init: function (relative, base) { var r = {}; base = base || {}; $.extend(this, parseURI(relative)); if (this.scheme === undefined) { this.scheme = base.scheme; if (this.authority !== undefined) { this.path = removeDotSegments(this.path); } else { this.authority = base.authority; if (this.path === '') { this.path = base.path; if (this.query === undefined) { this.query = base.query; } } else { if (!/^\//.test(this.path)) { this.path = merge(base, this.path); } this.path = removeDotSegments(this.path); } } } if (this.scheme === undefined) { throw "Malformed URI: URI is not an absolute URI and no base supplied: " + relative; } return this; }, /** * Resolves a relative URI relative to this URI * @param {String} relative * @returns jQuery.uri */ resolve: function (relative) { return $.uri(relative, this); }, /** * Creates a relative URI giving the path from this URI to the absolute URI passed as a parameter * @param {String|jQuery.uri} absolute * @returns String */ relative: function (absolute) { var aPath, bPath, i = 0, j, resultPath = [], result = ''; if (typeof absolute === 'string') { absolute = $.uri(absolute, {}); } if (absolute.scheme !== this.scheme || absolute.authority !== this.authority) { return absolute.toString(); } if (absolute.path !== this.path) { aPath = absolute.path.split('/'); bPath = this.path.split('/'); if (aPath[1] !== bPath[1]) { result = absolute.path; } else { while (aPath[i] === bPath[i]) { i += 1; } j = i; for (; i < bPath.length - 1; i += 1) { resultPath.push('..'); } for (; j < aPath.length; j += 1) { resultPath.push(aPath[j]); } result = resultPath.join('/'); } result = absolute.query === undefined ? result : result + '?' + absolute.query; result = absolute.fragment === undefined ? result : result + '#' + absolute.fragment; return result; } if (absolute.query !== undefined && absolute.query !== this.query) { return '?' + absolute.query + (absolute.fragment === undefined ? '' : '#' + absolute.fragment); } if (absolute.fragment !== undefined && absolute.fragment !== this.fragment) { return '#' + absolute.fragment; } return ''; }, /** * Returns the URI as an absolute string * @returns String */ toString: function () { var result = ''; if (this._string) { return this._string; } else { result = this.scheme === undefined ? result : (result + this.scheme + ':'); result = this.authority === undefined ? result : (result + '//' + this.authority); result = result + this.path; result = this.query === undefined ? result : (result + '?' + this.query); result = this.fragment === undefined ? result : (result + '#' + this.fragment); this._string = result; return result; } } }; $.uri.fn.init.prototype = $.uri.fn; /** * Creates a {@link jQuery.uri} from a known-to-be-absolute URI * @param {String} * @returns {jQuery.uri} */ $.uri.absolute = function (uri) { return $.uri(uri, {}); }; /** * Creates a {@link jQuery.uri} from a relative URI and an optional base URI * @returns {jQuery.uri} * @see jQuery.uri */ $.uri.resolve = function (relative, base) { return $.uri(relative, base); }; /** * Creates a string giving the relative path from a base URI to an absolute URI * @param {String} absolute * @param {String} base * @returns {String} */ $.uri.relative = function (absolute, base) { return $.uri(base, {}).relative(absolute); }; /** * Returns the base URI of the page * @returns {jQuery.uri} */ $.uri.base = function () { return $(document).base(); }; /** * Returns the base URI in scope for the first selected element * @methodOf jQuery# * @name jQuery#base * @returns {jQuery.uri} * @example baseURI = $('img').base(); */ $.fn.base = function () { var base = $(this).parents().andSelf().find('base').attr('href'), doc = $(this)[0].ownerDocument || document, docURI = $.uri.absolute(doc.location === null ? document.location.href : doc.location.href); return base === undefined ? docURI : $.uri(base, docURI); }; })(jQuery); /* * jQuery CURIE @VERSION * * Copyright (c) 2008,2009 Jeni Tennison * Licensed under the MIT (MIT-LICENSE.txt) * * Depends: * jquery.uri.js */ /** * @fileOverview XML Namespace processing * @author Jeni Tennison * @copyright (c) 2008,2009 Jeni Tennison * @license MIT license (MIT-LICENSE.txt) * @version 1.0 * @requires jquery.uri.js */ /*global jQuery */ (function ($) { var xmlnsRegex = /\sxmlns(?::([^ =]+))?\s*=\s*(?:"([^"]*)"|'([^']*)')/g; /** * Returns the namespaces declared in the scope of the first selected element, or * adds a namespace declaration to all selected elements. Pass in no parameters * to return all namespaces bindings on the first selected element. If only * the prefix parameter is specified, this method will return the namespace * URI that is bound to the specified prefix on the first element in the selection * If the prefix and uri parameters are both specified, this method will * add the binding of the specified prefix and namespace URI to all elements * in the selection. * @methodOf jQuery# * @name jQuery#xmlns * @param {String} [prefix] Restricts the namespaces returned to only the namespace with the specified namespace prefix. * @param {String|jQuery.uri} [uri] Adds a namespace declaration to the selected elements that maps the specified prefix to the specified namespace. * @param {Object} [inherited] A map of inherited namespace bindings. * @returns {Object|jQuery.uri|jQuery} * @example * // Retrieve all of the namespace bindings on the HTML document element * var nsMap = $('html').xmlns(); * @example * // Retrieve the namespace URI mapped to the 'dc' prefix on the HTML document element * var dcNamespace = $('html').xmlns('dc'); * @example * // Create a namespace declaration that binds the 'dc' prefix to the URI 'http://purl.org/dc/elements/1.1/' * $('html').xmlns('dc', 'http://purl.org/dc/elements/1.1/'); */ $.fn.xmlns = function (prefix, uri, inherited) { var elem = this.eq(0), ns = elem.data('xmlns'), e = elem[0], a, p, i, decl = prefix ? 'xmlns:' + prefix : 'xmlns', value, tag, found = false; if (uri === undefined) { if (prefix === undefined) { // get the in-scope declarations on the first element if (ns === undefined) { ns = {}; if (e.attributes && e.attributes.getNamedItemNS) { for (i = 0; i < e.attributes.length; i += 1) { a = e.attributes[i]; if (/^xmlns(:(.+))?$/.test(a.nodeName)) { prefix = /^xmlns(:(.+))?$/.exec(a.nodeName)[2] || ''; value = a.nodeValue; if (prefix === '' || value !== '') { ns[prefix] = $.uri(a.nodeValue); found = true; } } } } else { tag = /<[^>]+>/.exec(e.outerHTML); a = xmlnsRegex.exec(tag); while (a !== null) { prefix = a[1] || ''; value = a[2] || a[3]; if (prefix === '' || value !== '') { ns[prefix] = $.uri(a[2] || a[3]); found = true; } a = xmlnsRegex.exec(tag); } xmlnsRegex.lastIndex = 0; } inherited = inherited || (e.parentNode.nodeType === 1 ? elem.parent().xmlns() : {}); ns = found ? $.extend({}, inherited, ns) : inherited; elem.data('xmlns', ns); } return ns; } else if (typeof prefix === 'object') { // set the prefix mappings defined in the object for (p in prefix) { if (typeof prefix[p] === 'string') { this.xmlns(p, prefix[p]); } } this.find('*').andSelf().removeData('xmlns'); return this; } else { // get the in-scope declaration associated with this prefix on the first element if (ns === undefined) { ns = elem.xmlns(); } return ns[prefix]; } } else { // set this.find('*').andSelf().removeData('xmlns'); return this.attr(decl, uri); } }; /** * Removes one or more XML namespace bindings from the selected elements. * @methodOf jQuery# * @name jQuery#removeXmlns * @param {String|Object|String[]} prefix The prefix(es) of the XML namespace bindings that are to be removed from the selected elements. * @returns {jQuery} The original jQuery object. * @example * // Remove the foaf namespace declaration from the body element: * $('body').removeXmlns('foaf'); * @example * // Remove the foo and bar namespace declarations from all h2 elements * $('h2').removeXmlns(['foo', 'bar']); * @example * // Remove the foo and bar namespace declarations from all h2 elements * var namespaces = { foo : 'http://www.example.org/foo', bar : 'http://www.example.org/bar' }; * $('h2').removeXmlns(namespaces); */ $.fn.removeXmlns = function (prefix) { var decl, p, i; if (typeof prefix === 'object') { if (prefix.length === undefined) { // assume an object representing namespaces for (p in prefix) { if (typeof prefix[p] === 'string') { this.removeXmlns(p); } } } else { // it's an array for (i = 0; i < prefix.length; i += 1) { this.removeXmlns(prefix[i]); } } } else { decl = prefix ? 'xmlns:' + prefix : 'xmlns'; this.removeAttr(decl); } this.find('*').andSelf().removeData('xmlns'); return this; }; $.fn.qname = function (name) { var m, prefix, namespace; if (name === undefined) { if (this[0].outerHTML === undefined) { name = this[0].nodeName.toLowerCase(); } else { name = /<([^ >]+)/.exec(this[0].outerHTML)[1].toLowerCase(); } } if (name === '?xml:namespace') { // there's a prefix on the name, but we can't get at it throw "XMLinHTML: Unable to get the prefix to resolve the name of this element"; } m = /^(([^:]+):)?([^:]+)$/.exec(name); prefix = m[2] || ''; namespace = this.xmlns(prefix); if (namespace === undefined && prefix !== '') { throw "MalformedQName: The prefix " + prefix + " is not declared"; } return { namespace: namespace, localPart: m[3], prefix: prefix, name: name }; }; })(jQuery); /* * jQuery CURIE @VERSION * * Copyright (c) 2008,2009 Jeni Tennison * Licensed under the MIT (MIT-LICENSE.txt) * * Depends: * jquery.uri.js */ /** * @fileOverview XML Schema datatype handling * @author Jeni Tennison * @copyright (c) 2008,2009 Jeni Tennison * @license MIT license (MIT-LICENSE.txt) * @version 1.0 * @requires jquery.uri.js */ (function ($) { var strip = function (value) { return value.replace(/[ \t\n\r]+/, ' ').replace(/^ +/, '').replace(/ +$/, ''); }; /** * Creates a new jQuery.typedValue object. This should be invoked as a method * rather than constructed using new. * @class Represents a value with an XML Schema datatype * @param {String} value The string representation of the value * @param {String} datatype The XML Schema datatype URI * @returns {jQuery.typedValue} * @example intValue = jQuery.typedValue('42', 'http://www.w3.org/2001/XMLSchema#integer'); */ $.typedValue = function (value, datatype) { return $.typedValue.fn.init(value, datatype); }; $.typedValue.fn = $.typedValue.prototype = { /** * The string representation of the value * @memberOf jQuery.typedValue# */ representation: undefined, /** * The value as an object. The type of the object will * depend on the XML Schema datatype URI specified * in the constructor. The following table lists the mappings * currently supported: *
XML Schema Datatype | *Value type | *
---|---|
http://www.w3.org/2001/XMLSchema#string | *string | *
http://www.w3.org/2001/XMLSchema#boolean | *bool | *
http://www.w3.org/2001/XMLSchema#decimal | *string | *
http://www.w3.org/2001/XMLSchema#integer | *int | *
http://www.w3.org/2001/XMLSchema#int | *int | *
http://www.w3.org/2001/XMLSchema#float | *float | *
http://www.w3.org/2001/XMLSchema#double | *float | *
http://www.w3.org/2001/XMLSchema#dateTime | *string | *
http://www.w3.org/2001/XMLSchema#date | *string | *
http://www.w3.org/2001/XMLSchema#gMonthDay | *string | *
http://www.w3.org/2001/XMLSchema#anyURI | *string | *
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}.
* @classA 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}.
*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 [n]
, but you can also iterate through the matches using {@link jQuery.rdf#map} or {@link jQuery.rdf#each}.
{@link jQuery.rdf} is designed to mirror the functionality of SPARQL while providing an interface that's familiar and easy to use for jQuery programmers.
* @param {Object} [options] * @param {jQuery.rdf.databank} [options.databank] The databank that this query should operate over. * @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. * @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. * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the query. * @returns {jQuery.rdf} * @example rdf = jQuery.rdf(); * @see jQuery#rdf */ $.rdf = function (options) { return new $.rdf.fn.init(options); }; $.rdf.fn = $.rdf.prototype = { /** * The version of rdfQuery. * @type String */ rdfquery: '0.9', init: function (options) { var databanks; options = options || {}; /* must specify either a parent or a union, otherwise it's the top */ this.parent = options.parent; this.union = options.union; this.top = this.parent === undefined && this.union === undefined; if (this.union === undefined) { if (options.databank === undefined) { /** * The databank over which this query operates. * @type jQuery.rdf.databank */ this.databank = this.parent === undefined ? $.rdf.databank(options.triples, options) : this.parent.databank; } else { this.databank = options.databank; } } else { databanks = $.map(this.union, function (query) { return query.databank; }); databanks = $.unique(databanks); if (databanks[1] !== undefined) { this.databank = $.rdf.databank(undefined, { union: databanks }); } else { this.databank = databanks[0]; } } this.children = []; this.partOf = []; this.filterExp = options.filter; this.alphaMemory = []; this.matches = []; /** * The number of matches represented by the {@link jQuery.rdf} object. * @type Integer */ this.length = 0; if (this.filterExp !== undefined) { if (!$.isFunction(this.filterExp)) { registerQuery(this.databank, this); this.alphaMemory = findMatches(this.databank.triples(), this.filterExp); } } leftActivate(this); return this; }, /** * Sets or returns the base URI of the {@link jQuery.rdf#databank}. * @param {String|jQuery.uri} [base] * @returns A {@link jQuery.uri} if no base URI is specified, otherwise returns this {@link jQuery.rdf} object. * @example baseURI = jQuery('html').rdf().base(); * @example jQuery('html').rdf().base('http://www.example.org/'); * @see jQuery.rdf.databank#base */ base: function (base) { if (base === undefined) { return this.databank.base(); } else { this.databank.base(base); return this; } }, /** * Sets or returns a namespace binding on the {@link jQuery.rdf#databank}. * @param {String} [prefix] * @param {String} [namespace] * @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. * @example namespace = jQuery('html').rdf().prefix('foaf'); * @example jQuery('html').rdf().prefix('foaf', 'http://xmlns.com/foaf/0.1/'); * @see jQuery.rdf.databank#prefix */ prefix: function (prefix, namespace) { if (namespace === undefined) { return this.databank.prefix(prefix); } else { this.databank.prefix(prefix, namespace); return this; } }, /** * Adds a triple to the {@link jQuery.rdf#databank} or another {@link jQuery.rdf} object to create a union. * @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. * @param {Object} [options] * @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}. * @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}. * @returns {jQuery.rdf} This {@link jQuery.rdf} object. * @example * var rdf = $.rdf() * .prefix('dc', ns.dc) * .prefix('foaf', ns.foaf) * .add('<photo1.jpg> dc:creator <http://www.blogger.com/profile/1109404> .') * .add('<http://www.blogger.com/profile/1109404> foaf:img <photo1.jpg> .'); * @example * var rdfA = $.rdf() * .prefix('dc', ns.dc) * .add('<photo1.jpg> dc:creator "Jane"'); * var rdfB = $.rdf() * .prefix('foaf', ns.foaf) * .add('<photo1.jpg> foaf:depicts "Jane"'); * var rdf = rdfA.add(rdfB); * @see jQuery.rdf.databank#add */ add: function (triple, options) { var query, databank; if (triple.rdfquery !== undefined) { if (triple.top) { databank = this.databank.add(triple.databank); query = $.rdf({ parent: this.parent, databank: databank }); return query; } else if (this.top) { databank = triple.databank.add(this.databank); query = $.rdf({ parent: triple.parent, databank: databank }); return query; } else if (this.union === undefined) { query = $.rdf({ union: [this, triple] }); this.partOf.push(query); triple.partOf.push(query); return query; } else { this.union.push(triple); triple.partOf.push(this); } } else { if (typeof triple === 'string') { options = $.extend({}, { base: this.base(), namespaces: this.prefix(), source: triple }, options); triple = $.rdf.pattern(triple, options); } if (triple.isFixed()) { this.databank.add(triple.triple(), options); } else { query = this; this.each(function (i, data) { var t = triple.triple(data); if (t !== null) { query.databank.add(t, options); } }); } } return this; }, /** * Removes a triple or several triples from the {@link jQuery.rdf#databank}. * @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. * @param {Object} [options] * @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}. * @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}. * @returns {jQuery.rdf} The {@link jQuery.rdf} object itself. * @example * var rdf = $('html').rdf() * .prefix('foaf', ns.foaf) * .where('?person foaf:givenname ?gname') * .where('?person foaf:family_name ?fname') * .remove('?person foaf:family_name ?fname'); * @see jQuery.rdf.databank#remove */ remove: function (triple, options) { if (typeof triple === 'string') { options = $.extend({}, { base: this.base(), namespaces: this.prefix() }, options); triple = $.rdf.pattern(triple, options); } if (triple.isFixed()) { this.databank.remove(triple.triple(), options); } else { query = this; this.each(function (i, data) { var t = triple.triple(data); if (t !== null) { query.databank.remove(t, options); } }); } return this; }, /** * Loads some data into the {@link jQuery.rdf#databank} * @param data * @param {Object} [options] * @see jQuery.rdf.databank#load */ load: function (data, options) { this.databank.load(data, options); return this; }, /** * 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. * @param {jQuery.rdf} query * @see jQuery.rdf.databank#except */ except: function (query) { return $.rdf({ databank: this.databank.except(query.databank) }); }, /** * 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. * @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}. * @param {Object} [options] * @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}. * @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}. * @param {boolean} [options.optional] Not usually used (use {@link jQuery.rdf#optional} instead). * @returns {jQuery.rdf} A new {@link jQuery.rdf} object whose {@link jQuery.rdf#parent} is this {@link jQuery.rdf}. * @see jQuery.rdf#optional * @see jQuery.rdf#filter * @see jQuery.rdf#about * @example * var rdf = $.rdf() * .prefix('foaf', ns.foaf) * .add('_:a foaf:givenname "Alice" .') * .add('_:a foaf:family_name "Hacker" .') * .add('_:b foaf:givenname "Bob" .') * .add('_:b foaf:family_name "Hacker" .') * .where('?person foaf:family_name "Hacker"') * .where('?person foaf:givenname "Bob"); */ where: function (filter, options) { var query, base, namespaces, optional; options = options || {}; if (typeof filter === 'string') { base = options.base || this.base(); namespaces = $.extend({}, this.prefix(), options.namespaces || {}); optional = options.optional || false; filter = $.rdf.pattern(filter, { namespaces: namespaces, base: base, optional: optional }); } query = $.rdf($.extend({}, options, { parent: this, filter: filter })); this.children.push(query); return query; }, /** * Creates a new {@link jQuery.rdf} object whose set of bindings might optionally include those based on the filter pattern. * @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. * @param {Object} [options] * @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}. * @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}. * @returns {jQuery.rdf} A new {@link jQuery.rdf} object whose {@link jQuery.rdf#parent} is this {@link jQuery.rdf}. * @see jQuery.rdf#where * @see jQuery.rdf#filter * @see jQuery.rdf#about * @example * var rdf = $.rdf() * .prefix('foaf', 'http://xmlns.com/foaf/0.1/') * .prefix('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#') * .add('_:a rdf:type foaf:Person .') * .add('_:a foaf:name "Alice" .') * .add('_:a foaf:mbox <mailto:alice@example.com> .') * .add('_:a foaf:mbox <mailto:alice@work.example> .') * .add('_:b rdf:type foaf:Person .') * .add('_:b foaf:name "Bob" .') * .where('?x foaf:name ?name') * .optional('?x foaf:mbox ?mbox'); */ optional: function (filter, options) { return this.where(filter, $.extend({}, options || {}, { optional: true })); }, /** * Creates a new {@link jQuery.rdf} object whose set of bindings includeproperty
and value
for every triple that is about the specified resource.
* @param {String|jQuery.rdf.resource} resource The subject of the matching triples.
* @param {Object} [options]
* @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}.
* @param {String|jQuery.uri} [options.base] The base URI used to interpret the resource if it's a relative URI (wrapped in <
and >
). Defaults to the base URI defined on the {@link jQuery.rdf#databank}.
* @returns {jQuery.rdf} A new {@link jQuery.rdf} object whose {@link jQuery.rdf#parent} is this {@link jQuery.rdf}.
* @see jQuery.rdf#where
* @see jQuery.rdf#optional
* @see jQuery.rdf#filter
* @example
* var rdf = $.rdf()
* .prefix('dc', ns.dc)
* .prefix('foaf', ns.foaf)
* .add('<photo1.jpg> dc:creator <http://www.blogger.com/profile/1109404> .')
* .add('<http://www.blogger.com/profile/1109404> foaf:img <photo1.jpg> .')
* .add('<photo2.jpg> dc:creator <http://www.blogger.com/profile/1109404> .')
* .add('<http://www.blogger.com/profile/1109404> foaf:img <photo2.jpg> .')
* .about('<http://www.blogger.com/profile/1109404>');
*/
about: function (resource, options) {
return this.where(resource + ' ?property ?value', options);
},
/**
* 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.
* @param {Function|String} property 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 this
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:
this
)?
) are taken as variable names; each matching resource is described by the function.
* @returns {jQuery} A {@link jQuery} object that contains {@link jQuery.rdf.triple}s that describe the listed resources.
* @see jQuery.rdf.databank#describe
* @example
* $.rdf.dump($('html').rdf().describe(['this
is set to the object representing the variable bindings. The function can take up to three parameters:
* this
.this
is set to the object representing the variable bindings. The function can take up to three parameters and should return some kind of value:
* this
.mime type | description |
---|---|
application/json |
* An RDF/JSON object | *
application/rdf+xml |
* An DOMDocument node holding XML in RDF/XML syntax | *
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.
* @class Represents a triplestore, holding a bunch of {@link jQuery.rdf.triple}s. * @param {(String|jQuery.rdf.triple)[]} [triples=[]] An array of triples to store in the databank. * @param {Object} [options] Initialisation of the databank. * @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. * @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the strings representing triples. * @returns {jQuery.rdf.databank} The newly-created databank. * @see jQuery.rdf */ $.rdf.databank = function (triples, options) { return new $.rdf.databank.fn.init(triples, options); }; $.rdf.databank.fn = $.rdf.databank.prototype = { init: function (triples, options) { var i; triples = triples || []; options = options || {}; this.id = databankID(); if (options.union === undefined) { this.queries = {}; this.tripleStore = {}; this.objectStore = {}; this.baseURI = options.base || $.uri.base(); this.namespaces = $.extend({}, options.namespaces || {}); for (i = 0; i < triples.length; i += 1) { this.add(triples[i]); } } else { this.union = options.union; } return this; }, /** * Sets or returns the base URI of the {@link jQuery.rdf.databank}. * @param {String|jQuery.uri} [base] * @returns A {@link jQuery.uri} if no base URI is specified, otherwise returns this {@link jQuery.rdf.databank} object. * @see jQuery.rdf#base */ base: function (base) { if (this.union === undefined) { if (base === undefined) { return this.baseURI; } else { this.baseURI = base; return this; } } else if (base === undefined) { return this.union[0].base(); } else { $.each(this.union, function (i, databank) { databank.base(base); }); return this; } }, /** * Sets or returns a namespace binding on the {@link jQuery.rdf.databank}. * @param {String} [prefix] * @param {String} [namespace] * @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. * @see jQuery.rdf#prefix */ prefix: function (prefix, uri) { var namespaces = {}; if (this.union === undefined) { if (prefix === undefined) { return this.namespaces; } else if (uri === undefined) { return this.namespaces[prefix]; } else { this.namespaces[prefix] = uri; return this; } } else if (uri === undefined) { $.each(this.union, function (i, databank) { $.extend(namespaces, databank.prefix()); }); if (prefix === undefined) { return namespaces; } else { return namespaces[prefix]; } } else { $.each(this.union, function (i, databank) { databank.prefix(prefix, uri); }); return this; } }, /** * Adds a triple to the {@link jQuery.rdf.databank} or another {@link jQuery.rdf.databank} object to create a union. * @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}. * @param {Object} [options] * @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}. * @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}. * @returns {jQuery.rdf.databank} This {@link jQuery.rdf.databank} object. * @see jQuery.rdf#add */ add: function (triple, options) { var base = (options && options.base) || this.base(), namespaces = $.extend({}, this.prefix(), (options && options.namespaces) || {}), databank; if (triple === this) { return this; } else if (triple.tripleStore !== undefined) { // merging two databanks if (this.union === undefined) { databank = $.rdf.databank(undefined, { union: [this, triple] }); return databank; } else { this.union.push(triple); return this; } } else { if (typeof triple === 'string') { triple = $.rdf.triple(triple, { namespaces: namespaces, base: base, source: triple }); } if (this.union === undefined) { if (this.tripleStore[triple.subject] === undefined) { this.tripleStore[triple.subject] = []; } if ($.inArray(triple, this.tripleStore[triple.subject]) === -1) { this.tripleStore[triple.subject].push(triple); if (triple.object.type === 'uri' || triple.object.type === 'bnode') { if (this.objectStore[triple.object] === undefined) { this.objectStore[triple.object] = []; } this.objectStore[triple.object].push(triple); } addToDatabankQueries(this, triple); } } else { $.each(this.union, function (i, databank) { databank.add(triple); }); } return this; } }, /** * Removes a triple from the {@link jQuery.rdf.databank}. * @param {String|jQuery.rdf.triple} triple The triple to be removed. * @param {Object} [options] * @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}. * @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}. * @returns {jQuery.rdf.databank} The {@link jQuery.rdf.databank} object itself. * @see jQuery.rdf#remove */ remove: function (triple, options) { var base = (options && options.base) || this.base(), namespaces = $.extend({}, this.prefix(), (options && options.namespaces) || {}), striples, otriples, databank; if (typeof triple === 'string') { triple = $.rdf.triple(triple, { namespaces: namespaces, base: base, source: triple }); } striples = this.tripleStore[triple.subject]; if (striples !== undefined) { striples.splice($.inArray(triple, striples), 1); } if (triple.object.type === 'uri' || triple.object.type === 'bnode') { otriples = this.objectStore[triple.object]; if (otriples !== undefined) { otriples.splice($.inArray(triple, otriples), 1); } } removeFromDatabankQueries(this, triple); return this; }, /** * 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. * @param {jQuery.rdf.databank} data The other {@link jQuery.rdf.databank} * @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. * @example * var old = $('html').rdf().databank; * ...some processing occurs... * var new = $('html').rdf().databank; * var added = new.except(old); * var removed = old.except(new); */ except: function (data) { var store = data.tripleStore, diff = []; $.each(this.tripleStore, function (s, ts) { var ots = store[s]; if (ots === undefined) { diff = diff.concat(ts); } else { $.each(ts, function (i, t) { if ($.inArray(t, ots) === -1) { diff.push(t); } }); } }); return $.rdf.databank(diff); }, /** * Provides a {@link jQuery} object containing the triples held in this {@link jQuery.rdf.databank}. * @returns {jQuery} A {@link jQuery} object containing {@link jQuery.rdf.triple} objects. */ triples: function () { var triples = []; if (this.union === undefined) { $.each(this.tripleStore, function (s, t) { triples = triples.concat(t); }); } else { $.each(this.union, function (i, databank) { triples = triples.concat(databank.triples().get()); }); triples = $.unique(triples); } return $(triples); }, /** * Tells you how many triples the databank contains. * @returns {Integer} The number of triples in the {@link jQuery.rdf.databank}. * @example $('html').rdf().databank.size(); */ size: function () { return this.triples().length; }, /** * Provides simple concise bounded descriptions of the resources that are passed in the argument. This mirrors the DESCRIBE form in SPARQL. * @param {(String|jQuery.rdf.resource)[]} resources An array that can contain strings, {@link jQuery.rdf.resource}s or a mixture of the two. * @returns {jQuery} A {@link jQuery} object holding the {@link jQuery.rdf.triple}s that describe the listed resources. * @see jQuery.rdf#describe */ describe: function (resources) { var i, r, t, rhash = {}, triples = []; while (resources.length > 0) { r = resources.pop(); if (rhash[r] === undefined) { if (r.value === undefined) { r = $.rdf.resource(r); } if (this.tripleStore[r] !== undefined) { for (i = 0; i < this.tripleStore[r].length; i += 1) { t = this.tripleStore[r][i]; triples.push(t); if (t.object.type === 'bnode') { resources.push(t.object); } } } if (this.objectStore[r] !== undefined) { for (i = 0; i < this.objectStore[r].length; i += 1) { t = this.objectStore[r][i]; triples.push(t); if (t.subject.type === 'bnode') { resources.push(t.subject); } } } rhash[r] = true; } } return $.unique(triples); }, /** * Dumps the triples in the databank into a format that can be shown to the user or sent to a server. * @param {Object} [options] Options that control the formatting of the triples. See {@link jQuery.rdf.dump} for details. * @returns {Object|Node|String} * @see jQuery.rdf.dump */ dump: function (options) { options = $.extend({ namespaces: this.namespaces, base: this.base }, options || {}); return $.rdf.dump(this.triples(), options); }, /** * Loads some data into the databank. * @param {Node|Object} data If the data is a node, it's interpreted to be an RDF/XML syntax document and will be parsed as such. Otherwise, it's taken to be a RDF/JSON object. The data cannot be a string; it must be parsed before it is passed to this function. * @returns {jQuery.rdf.databank} The {@link jQuery.rdf.databank} itself. * @see jQuery.rdf#load */ load: function (data) { var i, triples; if (data.ownerDocument !== undefined) { triples = parseRdfXml(data); } else { triples = parseJson(data); } for (i = 0; i < triples.length; i += 1) { this.add(triples[i]); } return this; }, /** * Provides a string representation of the databank which simply specifies how many triples it contains. * @returns {String} */ toString: function () { return '[Databank with ' + this.size() + ' triples]'; } }; $.rdf.databank.fn.init.prototype = $.rdf.databank.fn; /** *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}.
* @class Represents a pattern that may or may not match a given {@link jQuery.rdf.triple}. * @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 (<uri>
or curie
), a blank node (_:id
) or a variable placeholder (?name
).
* @param {String|jQuery.rdf.resource} [property] The property pattern. If the property is specified as a string, it can be a fixed resource (<uri>
or curie
) or a variable placeholder (?name
).
* @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 (<uri>
or curie
), a blank node (_:id
), a literal ("value"
) or a variable placeholder (?name
).
* @param {Object} [options] Initialisation of the pattern.
* @param {Object} [options.namespaces] An object representing a set of namespace bindings used when interpreting the CURIEs in the subject, property and object.
* @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the subject, property and object.
* @param {boolean} [options.optional]
* @returns {jQuery.rdf.pattern} The newly-created pattern.
* @throws {String} Errors if any of the strings are not in a recognised format.
* @example pattern = $.rdf.pattern('?person', $.rdf.type, 'foaf:Person', { namespaces: { foaf: "http://xmlns.com/foaf/0.1/" }});
* @example
* pattern = $.rdf.pattern('?person a foaf:Person', {
* namespaces: { foaf: "http://xmlns.com/foaf/0.1/" },
* optional: true
* });
* @see jQuery.rdf#where
* @see jQuery.rdf.resource
* @see jQuery.rdf.blank
* @see jQuery.rdf.literal
*/
$.rdf.pattern = function (subject, property, object, options) {
var pattern, m, optional;
// using a two-argument version; first argument is a Turtle statement string
if (object === undefined) {
options = property || {};
m = $.trim(subject).match(tripleRegex);
if (m.length === 3 || (m.length === 4 && m[3] === '.')) {
subject = m[0];
property = m[1];
object = m[2];
} else {
throw "Bad Pattern: Couldn't parse string " + subject;
}
optional = (options.optional === undefined) ? $.rdf.pattern.defaults.optional : options.optional;
}
if (memPattern[subject] &&
memPattern[subject][property] &&
memPattern[subject][property][object] &&
memPattern[subject][property][object][optional]) {
return memPattern[subject][property][object][optional];
}
pattern = new $.rdf.pattern.fn.init(subject, property, object, options);
if (memPattern[pattern.subject] &&
memPattern[pattern.subject][pattern.property] &&
memPattern[pattern.subject][pattern.property][pattern.object] &&
memPattern[pattern.subject][pattern.property][pattern.object][pattern.optional]) {
return memPattern[pattern.subject][pattern.property][pattern.object][pattern.optional];
} else {
if (memPattern[pattern.subject] === undefined) {
memPattern[pattern.subject] = {};
}
if (memPattern[pattern.subject][pattern.property] === undefined) {
memPattern[pattern.subject][pattern.property] = {};
}
if (memPattern[pattern.subject][pattern.property][pattern.object] === undefined) {
memPattern[pattern.subject][pattern.property][pattern.object] = {};
}
memPattern[pattern.subject][pattern.property][pattern.object][pattern.optional] = pattern;
return pattern;
}
};
$.rdf.pattern.fn = $.rdf.pattern.prototype = {
init: function (s, p, o, options) {
var opts = $.extend({}, $.rdf.pattern.defaults, options);
/**
* The placeholder for the subject of triples matching against this pattern.
* @type String|jQuery.rdf.resource|jQuery.rdf.blank
*/
this.subject = s.toString().substring(0, 1) === '?' ? s : subject(s, opts);
/**
* The placeholder for the property of triples matching against this pattern.
* @type String|jQuery.rdf.resource
*/
this.property = p.toString().substring(0, 1) === '?' ? p : property(p, opts);
/**
* The placeholder for the object of triples matching against this pattern.
* @type String|jQuery.rdf.resource|jQuery.rdf.blank|jQuery.rdf.literal
*/
this.object = o.toString().substring(0, 1) === '?' ? o : object(o, opts);
/**
* Whether the pattern should only optionally match against the triple
* @type boolean
*/
this.optional = opts.optional;
return this;
},
/**
* 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.
* @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.
* @returns {jQuery.rdf.pattern} A new {@link jQuery.rdf.pattern} object.
* @example
* pattern = $.rdf.pattern('?thing a ?class');
* // pattern2 matches all triples that indicate the classes of this page.
* pattern2 = pattern.fill({ thing: $.rdf.resource('<>') });
*/
fill: function (bindings) {
var s = this.subject,
p = this.property,
o = this.object;
if (typeof s === 'string' && bindings[s.substring(1)]) {
s = bindings[s.substring(1)];
}
if (typeof p === 'string' && bindings[p.substring(1)]) {
p = bindings[p.substring(1)];
}
if (typeof o === 'string' && bindings[o.substring(1)]) {
o = bindings[o.substring(1)];
}
return $.rdf.pattern(s, p, o, { optional: this.optional });
},
/**
* Creates a new Object holding variable bindings by matching the passed triple against this pattern.
* @param {jQuery.rdf.triple} triple A {@link jQuery.rdf.triple} for this pattern to match against.
* @returns {null|Object} An object containing the bindings of variables (as specified in this pattern) to values (as specified in the triple), or null
if the triple doesn't match the pattern.
* pattern = $.rdf.pattern('?thing a ?class');
* bindings = pattern.exec($.rdf.triple('<> a foaf:Person', { namespaces: ns }));
* thing = bindings.thing; // the resource for this page
* class = bindings.class; // a resource for foaf:Person
*/
exec: function (triple) {
var binding = {};
binding = testResource(triple.subject, this.subject, binding);
if (binding === null) {
return null;
}
binding = testResource(triple.property, this.property, binding);
if (binding === null) {
return null;
}
binding = testResource(triple.object, this.object, binding);
return binding;
},
/**
* Tests whether this pattern has any variable placeholders in it or not.
* @returns {boolean} True if the pattern doesn't contain any variable placeholders.
* @example
* $.rdf.pattern('?thing a ?class').isFixed(); // false
* $.rdf.pattern('<> a foaf:Person', { namespaces: ns }).isFixed(); // true
*/
isFixed: function () {
return typeof this.subject !== 'string' &&
typeof this.property !== 'string' &&
typeof this.object !== 'string';
},
/**
* Creates a new triple based on the bindings passed to the pattern, if possible.
* @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.
* @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.
* @example
* pattern = $.rdf.pattern('?thing a ?class');
* // triple is a new triple '<> a foaf:Person'
* triple = pattern.triple({
* thing: $.rdf.resource('<>'),
* class: $.rdf.resource('foaf:Person', { namespaces: ns })
* });
*/
triple: function (bindings) {
var t = this;
if (!this.isFixed()) {
t = this.fill(bindings);
}
if (t.isFixed()) {
return $.rdf.triple(t.subject, t.property, t.object, { source: this.toString() });
} else {
return null;
}
},
/**
* Returns a string representation of the pattern by concatenating the subject, property and object.
* @returns {String}
*/
toString: function () {
return this.subject + ' ' + this.property + ' ' + this.object;
}
};
$.rdf.pattern.fn.init.prototype = $.rdf.pattern.fn;
$.rdf.pattern.defaults = {
base: $.uri.base(),
namespaces: {},
optional: false
};
/**
* 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}.
* @class Represents an RDF triple. * @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 (<uri>
or curie
) or a blank node (_:id
).
* @param {String|jQuery.rdf.resource} [property] The property pattern. If the property is specified as a string, it must be a fixed resource (<uri>
or curie
).
* @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 (<uri>
or curie
), a blank node (_:id
), or a literal ("value"
).
* @param {Object} [options] Initialisation of the triple.
* @param {Object} [options.namespaces] An object representing a set of namespace bindings used when interpreting the CURIEs in the subject, property and object.
* @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the subject, property and object.
* @returns {jQuery.rdf.triple} The newly-created triple.
* @throws {String} Errors if any of the strings are not in a recognised format.
* @example pattern = $.rdf.triple('<>', $.rdf.type, 'foaf:Person', { namespaces: { foaf: "http://xmlns.com/foaf/0.1/" }});
* @example
* pattern = $.rdf.triple('<> a foaf:Person', {
* namespaces: { foaf: "http://xmlns.com/foaf/0.1/" }
* });
* @see jQuery.rdf#add
* @see jQuery.rdf.resource
* @see jQuery.rdf.blank
* @see jQuery.rdf.literal
*/
$.rdf.triple = function (subject, property, object, options) {
var triple, graph, m;
// using a two-argument version; first argument is a Turtle statement string
if (object === undefined) {
options = property;
m = $.trim(subject).match(tripleRegex);
if (m.length === 3 || (m.length === 4 && m[3] === '.')) {
subject = m[0];
property = m[1];
object = m[2];
} else {
throw "Bad Triple: Couldn't parse string " + subject;
}
}
graph = (options && options.graph) || '';
if (memTriple[graph] &&
memTriple[graph][subject] &&
memTriple[graph][subject][property] &&
memTriple[graph][subject][property][object]) {
return memTriple[graph][subject][property][object];
}
triple = new $.rdf.triple.fn.init(subject, property, object, options);
graph = triple.graph || '';
if (memTriple[graph] &&
memTriple[graph][triple.subject] &&
memTriple[graph][triple.subject][triple.property] &&
memTriple[graph][triple.subject][triple.property][triple.object]) {
return memTriple[graph][triple.subject][triple.property][triple.object];
} else {
if (memTriple[graph] === undefined) {
memTriple[graph] = {};
}
if (memTriple[graph][triple.subject] === undefined) {
memTriple[graph][triple.subject] = {};
}
if (memTriple[graph][triple.subject][triple.property] === undefined) {
memTriple[graph][triple.subject][triple.property] = {};
}
memTriple[graph][triple.subject][triple.property][triple.object] = triple;
return triple;
}
};
$.rdf.triple.fn = $.rdf.triple.prototype = {
init: function (s, p, o, options) {
var opts;
opts = $.extend({}, $.rdf.triple.defaults, options);
/**
* The subject of the triple.
* @type jQuery.rdf.resource|jQuery.rdf.blank
*/
this.subject = subject(s, opts);
/**
* The property of the triple.
* @type jQuery.rdf.resource
*/
this.property = property(p, opts);
/**
* The object of the triple.
* @type jQuery.rdf.resource|jQuery.rdf.blank|jQuery.rdf.literal
*/
this.object = object(o, opts);
/**
* (Experimental) The named graph the triple belongs to.
* @type jQuery.rdf.resource|jQuery.rdf.blank
*/
this.graph = opts.graph === undefined ? undefined : subject(opts.graph, opts);
/**
* 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.
*/
this.source = opts.source;
return this;
},
/**
* Always returns true for triples.
* @see jQuery.rdf.pattern#isFixed
*/
isFixed: function () {
return true;
},
/**
* Always returns this triple.
* @see jQuery.rdf.pattern#triple
*/
triple: function (bindings) {
return this;
},
/**
* Returns a RDF/JSON representation of this triple.
* @returns {Object}
*/
dump: function () {
var e = {},
s = this.subject.value.toString(),
p = this.property.value.toString();
e[s] = {};
e[s][p] = this.object.dump();
return e;
},
/**
* Returns a string representing this triple in Turtle format.
* @returns {String}
*/
toString: function () {
return this.subject + ' ' + this.property + ' ' + this.object + ' .';
}
};
$.rdf.triple.fn.init.prototype = $.rdf.triple.fn;
$.rdf.triple.defaults = {
base: $.uri.base(),
source: [document],
namespaces: {}
};
/**
* 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}.
* @class Represents an RDF resource. * @param {String|jQuery.uri} value The value of the resource. If it's a string it must be in the format<uri>
or curie
.
* @param {Object} [options] Initialisation of the resource.
* @param {Object} [options.namespaces] An object representing a set of namespace bindings used when interpreting the CURIE specifying the resource.
* @param {String|jQuery.uri} [options.base] The base URI used to interpret any relative URIs used within the URI specifying the resource.
* @returns {jQuery.rdf.resource} The newly-created resource.
* @throws {String} Errors if the string is not in a recognised format.
* @example thisPage = $.rdf.resource('<>');
* @example foaf.Person = $.rdf.resource('foaf:Person', { namespaces: ns });
* @see jQuery.rdf.pattern
* @see jQuery.rdf.triple
* @see jQuery.rdf.blank
* @see jQuery.rdf.literal
*/
$.rdf.resource = function (value, options) {
var resource;
if (memResource[value]) {
return memResource[value];
}
resource = new $.rdf.resource.fn.init(value, options);
if (memResource[resource]) {
return memResource[resource];
} else {
memResource[resource] = resource;
return resource;
}
};
$.rdf.resource.fn = $.rdf.resource.prototype = {
/**
* Always fixed to 'uri' for resources.
* @type String
*/
type: 'uri',
/**
* The URI for the resource.
* @type jQuery.rdf.uri
*/
value: undefined,
init: function (value, options) {
var m, prefix, uri, opts;
if (typeof value === 'string') {
m = uriRegex.exec(value);
opts = $.extend({}, $.rdf.resource.defaults, options);
if (m !== null) {
this.value = $.uri.resolve(m[1].replace(/\\>/g, '>'), opts.base);
} else if (value.substring(0, 1) === ':') {
uri = opts.namespaces[''];
if (uri === undefined) {
throw "Malformed Resource: No namespace binding for default namespace in " + value;
} else {
this.value = $.uri.resolve(uri + value.substring(1));
}
} else if (value.substring(value.length - 1) === ':') {
prefix = value.substring(0, value.length - 1);
uri = opts.namespaces[prefix];
if (uri === undefined) {
throw "Malformed Resource: No namespace binding for prefix " + prefix + " in " + value;
} else {
this.value = $.uri.resolve(uri);
}
} else {
try {
this.value = $.curie(value, { namespaces: opts.namespaces });
} catch (e) {
throw "Malformed Resource: Bad format for resource " + e;
}
}
} else {
this.value = value;
}
return this;
}, // end init
/**
* Returns a RDF/JSON representation of this triple.
* @returns {Object}
*/
dump: function () {
return {
type: 'uri',
value: this.value.toString()
};
},
/**
* Returns a string representing this resource in Turtle format.
* @returns {String}
*/
toString: function () {
return '<' + this.value + '>';
}
};
$.rdf.resource.fn.init.prototype = $.rdf.resource.fn;
$.rdf.resource.defaults = {
base: $.uri.base(),
namespaces: {}
};
/**
* A {@link jQuery.rdf.resource} for rdf:type
* @constant
* @type jQuery.rdf.resource
*/
$.rdf.type = $.rdf.resource('<' + rdfNs + 'type>');
/**
* A {@link jQuery.rdf.resource} for rdfs:label
* @constant
* @type jQuery.rdf.resource
*/
$.rdf.label = $.rdf.resource('<' + rdfsNs + 'label>');
/**
* A {@link jQuery.rdf.resource} for rdf:first
* @constant
* @type jQuery.rdf.resource
*/
$.rdf.first = $.rdf.resource('<' + rdfNs + 'first>');
/**
* A {@link jQuery.rdf.resource} for rdf:rest
* @constant
* @type jQuery.rdf.resource
*/
$.rdf.rest = $.rdf.resource('<' + rdfNs + 'rest>');
/**
* A {@link jQuery.rdf.resource} for rdf:nil
* @constant
* @type jQuery.rdf.resource
*/
$.rdf.nil = $.rdf.resource('<' + rdfNs + 'nil>');
/**
* A {@link jQuery.rdf.resource} for rdf:subject
* @constant
* @type jQuery.rdf.resource
*/
$.rdf.subject = $.rdf.resource('<' + rdfNs + 'subject>');
/**
* A {@link jQuery.rdf.resource} for rdf:property
* @constant
* @type jQuery.rdf.resource
*/
$.rdf.property = $.rdf.resource('<' + rdfNs + 'property>');
/**
* A {@link jQuery.rdf.resource} for rdf:object
* @constant
* @type jQuery.rdf.resource
*/
$.rdf.object = $.rdf.resource('<' + rdfNs + 'object>');
/**
* 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}.
* @class Represents an RDF blank node. * @param {String} value A representation of the blank node in the format_:id
or []
(which automatically creates a new blank node with a unique ID).
* @returns {jQuery.rdf.blank} The newly-created blank node.
* @throws {String} Errors if the string is not in a recognised format.
* @example newBlank = $.rdf.blank('[]');
* @example identifiedBlank = $.rdf.blank('_:fred');
* @see jQuery.rdf.pattern
* @see jQuery.rdf.triple
* @see jQuery.rdf.resource
* @see jQuery.rdf.literal
*/
$.rdf.blank = function (value) {
var blank;
if (memBlank[value]) {
return memBlank[value];
}
blank = new $.rdf.blank.fn.init(value);
if (memBlank[blank]) {
return memBlank[blank];
} else {
memBlank[blank] = blank;
return blank;
}
};
$.rdf.blank.fn = $.rdf.blank.prototype = {
/**
* Always fixed to 'bnode' for blank nodes.
* @type String
*/
type: 'bnode',
/**
* The value of the blank node in the format _:id
* @type String
*/
value: undefined,
/**
* The id of the blank node.
* @type String
*/
id: undefined,
init: function (value) {
if (value === '[]') {
this.id = blankNodeID();
this.value = '_:' + this.id;
} else if (value.substring(0, 2) === '_:') {
this.id = value.substring(2);
this.value = value;
} else {
throw "Malformed Blank Node: " + value + " is not a legal format for a blank node";
}
return this;
},
/**
* Returns a RDF/JSON representation of this blank node.
* @returns {Object}
*/
dump: function () {
return {
type: 'bnode',
value: this.value
};
},
/**
* Returns the value this blank node.
* @returns {String}
*/
toString: function () {
return this.value;
}
};
$.rdf.blank.fn.init.prototype = $.rdf.blank.fn;
/**
* 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}.
* @class Represents an RDF literal. * @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 Turtle syntax. * @param {Object} [options] Initialisation options for the literal. * @param {String} [options.datatype] The datatype for the literal. This should be a safe CURIE; in other words, it can be in the formaturi
or [curie]
. Must not be specified if options.lang is also specified.
* @param {String} [options.lang] The language for the literal. Must not be specified if options.datatype is also specified.
* @param {Object} [options.namespaces] An object representing a set of namespace bindings used when interpreting a CURIE in the datatype.
* @param {String|jQuery.uri} [options.base] The base URI used to interpret a relative URI in the datatype.
* @returns {jQuery.rdf.literal} The newly-created literal.
* @throws {String} Errors if the string is not in a recognised format or if both options.datatype and options.lang are specified.
* @example trueLiteral = $.rdf.literal(true);
* @example numericLiteral = $.rdf.literal(5);
* @example dateLiteral = $.rdf.literal('"2009-07-13"^^xsd:date', { namespaces: ns });
* @see jQuery.rdf.pattern
* @see jQuery.rdf.triple
* @see jQuery.rdf.resource
* @see jQuery.rdf.blank
*/
$.rdf.literal = function (value, options) {
var literal;
if (memLiteral[value]) {
return memLiteral[value];
}
literal = new $.rdf.literal.fn.init(value, options);
if (memLiteral[literal]) {
return memLiteral[literal];
} else {
memLiteral[literal] = literal;
return literal;
}
};
$.rdf.literal.fn = $.rdf.literal.prototype = {
/**
* Always fixed to 'literal' for literals.
* @type String
*/
type: 'literal',
/**
* The value of the literal as a string.
* @type String
*/
value: undefined,
/**
* The language of the literal, if it has one; otherwise undefined.
* @type String
*/
lang: undefined,
/**
* The datatype of the literal, if it has one; otherwise undefined.
* @type jQuery.uri
*/
datatype: undefined,
init: function (value, options) {
var
m, datatype,
opts = $.extend({}, $.rdf.literal.defaults, options);
if (opts.lang !== undefined && opts.datatype !== undefined) {
throw "Malformed Literal: Cannot define both a language and a datatype for a literal (" + value + ")";
}
if (opts.datatype !== undefined) {
datatype = $.safeCurie(opts.datatype, { namespaces: opts.namespaces });
$.extend(this, $.typedValue(value.toString(), datatype));
} else if (opts.lang !== undefined) {
this.value = value.toString();
this.lang = opts.lang;
} else if (typeof value === 'boolean') {
$.extend(this, $.typedValue(value.toString(), xsdNs + 'boolean'));
} else if (typeof value === 'number') {
$.extend(this, $.typedValue(value.toString(), xsdNs + 'double'));
} else if (value === 'true' || value === 'false') {
$.extend(this, $.typedValue(value, xsdNs + 'boolean'));
} else if ($.typedValue.valid(value, xsdNs + 'integer')) {
$.extend(this, $.typedValue(value, xsdNs + 'integer'));
} else if ($.typedValue.valid(value, xsdNs + 'decimal')) {
$.extend(this, $.typedValue(value, xsdNs + 'decimal'));
} else if ($.typedValue.valid(value, xsdNs + 'double') &&
!/^\s*([\-\+]?INF|NaN)\s*$/.test(value)) { // INF, -INF and NaN aren't valid literals in Turtle
$.extend(this, $.typedValue(value, xsdNs + 'double'));
} else {
m = literalRegex.exec(value);
if (m !== null) {
this.value = (m[2] || m[4]).replace(/\\"/g, '"');
if (m[9]) {
datatype = $.rdf.resource(m[9], opts);
$.extend(this, $.typedValue(this.value, datatype.value));
} else if (m[7]) {
this.lang = m[7];
}
} else {
throw "Malformed Literal: Couldn't recognise the value " + value;
}
}
return this;
}, // end init
/**
* Returns a RDF/JSON representation of this blank node.
* @returns {Object}
*/
dump: function () {
var e = {
type: 'literal',
value: this.value.toString()
};
if (this.lang !== undefined) {
e.lang = this.lang;
} else if (this.datatype !== undefined) {
e.datatype = this.datatype.toString();
}
return e;
},
/**
* Returns a string representing this resource in Turtle format.
* @returns {String}
*/
toString: function () {
var val = '"' + this.value + '"';
if (this.lang !== undefined) {
val += '@' + this.lang;
} else if (this.datatype !== undefined) {
val += '^^<' + this.datatype + '>';
}
return val;
}
};
$.rdf.literal.fn.init.prototype = $.rdf.literal.fn;
$.rdf.literal.defaults = {
base: $.uri.base(),
namespaces: {},
datatype: undefined,
lang: undefined
};
})(jQuery);