From 96a612c88001cc1c2c2ad86cc3558df28a947fa2 Mon Sep 17 00:00:00 2001 From: sebastien Date: Sun, 12 Jan 2014 19:50:09 +0100 Subject: [PATCH] Replace RDFStore persistent version by inmemory version --- app/lib/rdf_store.js | 43067 ++++++++++++++++++++--------------------- 1 file changed, 21251 insertions(+), 21816 deletions(-) diff --git a/app/lib/rdf_store.js b/app/lib/rdf_store.js index ce3ca36..66d1f30 100644 --- a/app/lib/rdf_store.js +++ b/app/lib/rdf_store.js @@ -2,207 +2,207 @@ if(typeof(console)=='undefined') { - console = {}; - console.log = function(e){}; + console = {}; + console.log = function(e){}; } - + window.process = {}; process.nextTick = function(f) { setTimeout(f,0); }; - var Utils = {}; +var Utils = {}; - Utils['extends'] = function(supertype, descendant) { +Utils['extends'] = function(supertype, descendant) { descendant.prototype = new supertype(); - }; +}; - Utils.stackCounterLimit = 1000; - Utils.stackCounter = 0; +Utils.stackCounterLimit = 1000; +Utils.stackCounter = 0; - Utils.recur = function(c){ +Utils.recur = function(c){ if(Utils.stackCounter === Utils.stackCounterLimit) { - Utils.stackCounter = 0; - setTimeout(c, 0); + Utils.stackCounter = 0; + setTimeout(c, 0); } else { - Utils.stackCounter++; - c(); - } - }; + Utils.stackCounter++; + c(); + } +}; - Utils.clone = function(o) { +Utils.clone = function(o) { return JSON.parse(JSON.stringify(o)); - }; +}; - Utils.shuffle = function(o){ //v1.0 +Utils.shuffle = function(o){ //v1.0 for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x){}; return o; - }; +}; - Utils.include = function(a,v) { +Utils.include = function(a,v) { var cmp = arguments[2]; for(var i=(a.length-1); i>=0; i--) { - var res = false; - if(cmp == null) { - res = (a[i] === v); - } else { - res = (cmp(a[i],v) === 0); - } + var res = false; + if(cmp == null) { + res = (a[i] === v); + } else { + res = (cmp(a[i],v) === 0); + } - if(res === true) { - return true; - } + if(res === true) { + return true; + } } return false; - }; +}; - Utils.remove = function(a,v) { +Utils.remove = function(a,v) { var acum = []; for(var i=0; i tb && ta > (tb - offset)) { - return 1; - } else { + if(ta < tb && ta < (tb + offset)) { + return -1; + } else if(ta > tb && ta > (tb - offset)) { + return 1; + } else { return null; - } + } } else { - da = Utils.parseISO8601(stra); - db = Utils.parseISO8601(strb); - ta = da.getTime(); - tb = db.getTime(); - - var offset = 14*60*60; - if(ta < tb && (ta + offset) < tb) { - return -1; - } else if(ta > tb && (ta + offset) > tb) { - return 1; - } else { + da = Utils.parseISO8601(stra); + db = Utils.parseISO8601(strb); + ta = da.getTime(); + tb = db.getTime(); + + var offset = 14*60*60; + if(ta < tb && (ta + offset) < tb) { + return -1; + } else if(ta > tb && (ta + offset) > tb) { + return 1; + } else { return null; - } + } } - }; +}; // RDF utils - Utils.lexicalFormLiteral = function(term, env) { +Utils.lexicalFormLiteral = function(term, env) { var value = term.value; var lang = term.lang; var type = term.type; var indexedValue = null; if(value != null && type != null && typeof(type) != 'string') { - var typeValue = type.value; - - if(typeValue == null) { - var typePrefix = type.prefix; - var typeSuffix = type.suffix; - - var resolvedPrefix = env.namespaces[typePrefix]; - term.type = resolvedPrefix+typeSuffix; - typeValue = resolvedPrefix+typeSuffix; - } - // normalization - if(typeValue.indexOf('hexBinary') != -1) { - indexedValue = '"' + term.value.toLowerCase() + '"^^<' + typeValue + '>'; - } else { - indexedValue = '"' + term.value + '"^^<' + typeValue + '>'; - } + var typeValue = type.value; + + if(typeValue == null) { + var typePrefix = type.prefix; + var typeSuffix = type.suffix; + + var resolvedPrefix = env.namespaces[typePrefix]; + term.type = resolvedPrefix+typeSuffix; + typeValue = resolvedPrefix+typeSuffix; + } + // normalization + if(typeValue.indexOf('hexBinary') != -1) { + indexedValue = '"' + term.value.toLowerCase() + '"^^<' + typeValue + '>'; + } else { + indexedValue = '"' + term.value + '"^^<' + typeValue + '>'; + } } else { - if(lang == null && type == null) { - indexedValue = '"' + value + '"'; - } else if(type == null) { - indexedValue = '"' + value + '"' + "@" + lang; - } else { - // normalization - if(type.indexOf('hexBinary') != -1) { - indexedValue = '"' + term.value.toLowerCase() + '"^^<'+type+'>'; + if(lang == null && type == null) { + indexedValue = '"' + value + '"'; + } else if(type == null) { + indexedValue = '"' + value + '"' + "@" + lang; } else { - indexedValue = '"' + term.value + '"^^<'+type+'>'; + // normalization + if(type.indexOf('hexBinary') != -1) { + indexedValue = '"' + term.value.toLowerCase() + '"^^<'+type+'>'; + } else { + indexedValue = '"' + term.value + '"^^<'+type+'>'; + } } - } } return indexedValue; - }; +}; - Utils.lexicalFormBaseUri = function(term, env) { +Utils.lexicalFormBaseUri = function(term, env) { var uri = null; env = env || {}; //console.log("*** normalizing URI token:"); //console.log(term); if(term.value == null) { - //console.log(" - URI has prefix and suffix"); - //console.log(" - prefix:"+term.prefix); - //console.log(" - suffixx:"+term.suffix); - var prefix = term.prefix; - var suffix = term.suffix; - var resolvedPrefix = env.namespaces[prefix]; - if(resolvedPrefix != null) { - uri = resolvedPrefix+suffix; - } else { - uri = prefix+":"+suffix; - } + //console.log(" - URI has prefix and suffix"); + //console.log(" - prefix:"+term.prefix); + //console.log(" - suffixx:"+term.suffix); + var prefix = term.prefix; + var suffix = term.suffix; + var resolvedPrefix = env.namespaces[prefix]; + if(resolvedPrefix != null) { + uri = resolvedPrefix+suffix; + } else { + uri = prefix+":"+suffix; + } } else { - //console.log(" - URI is not prefixed"); - uri = term.value; + //console.log(" - URI is not prefixed"); + uri = term.value; } if(uri===null) { - return null; + return null; } else { - //console.log(" - resolved URI is "+uri); - if(uri.indexOf(":") == -1) { - //console.log(" - URI is partial"); - uri = (env.base||"") + uri; // applyBaseUri - } else { - //console.log(" - URI is complete"); - } - //console.log(" -> FINAL URI: "+uri); + //console.log(" - resolved URI is "+uri); + if(uri.indexOf(":") == -1) { + //console.log(" - URI is partial"); + uri = (env.base||"") + uri; // applyBaseUri + } else { + //console.log(" - URI is complete"); + } + //console.log(" -> FINAL URI: "+uri); } return uri; - }; +}; - Utils.lexicalFormTerm = function(term, ns) { +Utils.lexicalFormTerm = function(term, ns) { if(term.token === 'uri') { - return {'uri': Utils.lexicalFormBaseUri(term, ns)}; + return {'uri': Utils.lexicalFormBaseUri(term, ns)}; } else if(term.token === 'literal') { - return {'literal': Utils.lexicalFormLiteral(term, ns)}; + return {'literal': Utils.lexicalFormLiteral(term, ns)}; } else if(term.token === 'blank') { - var label = '_:'+term.value; - return {'blank': label}; + var label = '_:'+term.value; + return {'blank': label}; } else { - throw "Error, cannot get lexical form of unknown token: "+term.token; + throw "Error, cannot get lexical form of unknown token: "+term.token; } - }; +}; - Utils.normalizeUnicodeLiterals = function (string) { +Utils.normalizeUnicodeLiterals = function (string) { var escapedUnicode = string.match(/\\u[0-9abcdefABCDEF]{4,4}/g) || []; var dups = {}; for (var i = 0; i < escapedUnicode.length; i++) { - if (dups[escapedUnicode[i]] == null) { - dups[escapedUnicode[i]] = true; - string = string.replace(new RegExp("\\" + escapedUnicode[i], "g"), eval("'" + escapedUnicode[i] + "'")); - } + if (dups[escapedUnicode[i]] == null) { + dups[escapedUnicode[i]] = true; + string = string.replace(new RegExp("\\" + escapedUnicode[i], "g"), eval("'" + escapedUnicode[i] + "'")); + } } return string; - }; +}; - Utils.hashTerm = function(term) { +Utils.hashTerm = function(term) { try { if(term == null) { - return ""; + return ""; } if(term.token==='uri') { - return "u"+term.value; + return "u"+term.value; } else if(term.token === 'blank') { - return "b"+term.value; + return "b"+term.value; } else if(term.token === 'literal') { - var l = "l"+term.value; - l = l + (term.type || ""); - l = l + (term.lang || ""); - - return l; + var l = "l"+term.value; + l = l + (term.type || ""); + l = l + (term.lang || ""); + + return l; } } catch(e) { - if(typeof(term) === 'object') { - var key = ""; - for(p in term) { - key = key + p + term[p]; - } + if(typeof(term) === 'object') { + var key = ""; + for(p in term) { + key = key + p + term[p]; + } - return key; - } - return term; + return key; + } + return term; } - }; +}; // end of ./src/js-trees/src/utils.js // exports - var PriorityQueue = {}; - - /** - * @constructor - * @class PriorityQueue manages a queue of elements with priorities. Default - * is highest priority first. - * - * @param [options] If low is set to true returns lowest first. - */ - PriorityQueue.PriorityQueue = function(options) { - var contents = []; - var store = {}; - var sorted = false; - var sortStyle; - var maxSize = options.maxSize || 10; - - //noinspection UnnecessaryLocalVariableJS - sortStyle = function(a, b) { - return store[b].priority - store[a].priority; - }; +var InMemoryBTree = {}; +var left = -1; +var right = 1; - /** - * @private - */ - var sort = function() { - contents.sort(sortStyle); - sorted = true; - }; - - var self = { - debugContents: contents, - debugStore: store, - debugSort: sort, - - push: function(pointer, object) { - if(contents.length === maxSize) { - if(!sorted) { - sort(); - } - if(store[pointer] == null) { - delete store[contents[0]]; - contents[0] = pointer; - var priority = (store[contents[contents.length - 1]].priority) - 1; - store[pointer] = {object: object, priority: priority}; - sorted = false; - } else { - priority = (store[contents[contents.length - 1]].priority) - 1; - store[pointer].priority = priority; - sorted = false; - } - } else if(contents.length === 0){ - contents.push(pointer); - store[pointer] = {object: object, priority: 1000}; - } else { - priority = (store[contents[contents.length - 1]].priority) - 1; - if(store[pointer] == null) { - store[pointer] = {object: object, priority: priority}; - contents.push(pointer); - } else { - store[pointer].priority = priority; - sorted = false; - } - } - }, - - remove: function(pointer) { - if(store[pointer] != null) { - delete store[pointer]; - var pos = null; - for(var i=0; i + * + */ -// end of ./src/js-trees/src/priority_queue.js -// exports - var WebLocalStorageBTree = {}; - - var left = -1; - var right = 1; - - - /** - * @doc - * Implementation based on - * - */ +/** + * Tree + * + * Implements the interface of BinarySearchTree.Tree + * + * An implementation of an in memory B-Tree. + */ - /** - * Tree - * - * Implements the interface of BinarySearchTree.Tree - * - * An implementation of an in memory B-Tree. - */ - WebLocalStorageBTree.Tree = function(order, name, persistent, cacheMaxSize) { +InMemoryBTree.Tree = function(order) { if(arguments.length != 0) { - var storage = null; - if(persistent === true) { - try { - storage = window.localStorage; - if(storage == null) { - throw("not found"); - } - } catch(e) { - throw("Local storage is not present, cannot create persistent storage"); - } - } - - if(storage == null) { - storage = (function(){ - var content = {}; - return { setItem: function(pointer, object) { - content[pointer] = object; - }, - getItem: function(pointer) { - return (content[pointer] || null); - }, - removeItem: function(pointer) { - delete content[pointer]; - }, - get: function(i) { - var j=0; - for(var k in content) { - if(i===j) { - return k; - } - j++; - } - - return ""; - }, - length: content.length - }; - })(); - } - - this.storage = storage; - this.order = order; - this.name = name; - this.diskManager = new WebLocalStorageBTree.LocalStorageManager(name, storage, cacheMaxSize); - this.root = this.diskManager._readRootNode(); - //this.root = this.diskManager._diskRead("__"+name+"__ROOT_NODE__"); - if(this.root == null) { + this.order = order; this.root = this._allocateNode(); this.root.isLeaf = true; this.root.level = 0; this._diskWrite(this.root); this._updateRootNode(this.root); - this.root = this.root.pointer; - } else { - this.root = this.diskManager._diskRead(this.root).pointer; - }; - - this.comparator = function(a,b) { - if(a < b) { - return -1; - } else if(a > b){ - return 1; - } else { - return 0; - } - }; - this.merger = null; - } - }; - - - /** - * Creates the new node. - * - * This class can be overwritten by different versions of - * the tree t select the right kind of node to be used - * - * @returns the new alloacted node - */ - WebLocalStorageBTree.Tree.prototype._allocateNode = function() { - return new WebLocalStorageBTree.Node(); - }; - - /** - * _diskWrite - * - * Persists the node to secondary memory. - */ - WebLocalStorageBTree.Tree.prototype._diskWrite= function(node) { - this.diskManager._diskWrite(node); - }; - - - /** - * _diskRead - * - * Retrieves a node from secondary memory using the provided - * pointer - */ - WebLocalStorageBTree.Tree.prototype._diskRead = function(pointer) { - return this.diskManager._diskRead(pointer); - }; - - WebLocalStorageBTree.Tree.prototype._diskDelete = function(node) { - this.diskManager._diskDelete(node); - }; - - /** - * _updateRootNode - * - * Updates the pointer to the root node stored in disk. - */ - WebLocalStorageBTree.Tree.prototype._updateRootNode = function(node) { - this.diskManager._updateRootNode(node); + this.comparator = function(a,b) { + if(a < b) { + return -1; + } else if(a > b){ + return 1; + } else { + return 0; + } + }; + this.merger = null; + } +}; + +/** + * Creates the new node. + * + * This class can be overwritten by different versions of + * the tree t select the right kind of node to be used + * + * @returns the new alloacted node + */ +InMemoryBTree.Tree.prototype._allocateNode = function () { + return new InMemoryBTree.Node(); +}; + +/** + * _diskWrite + * + * Persists the node to secondary memory. + */ +InMemoryBTree.Tree.prototype._diskWrite= function(node) { + // dummy implementation; + // no-op +}; + + +/** + * _diskRead + * + * Retrieves a node from secondary memory using the provided + * pointer + */ +InMemoryBTree.Tree.prototype._diskRead = function(pointer) { + // dummy implementation; + // no-op + return pointer; +}; + + +InMemoryBTree.Tree.prototype._diskDelete= function(node) { + // dummy implmentation + // no-op +}; + +/** + * _updateRootNode + * + * Updates the pointer to the root node stored in disk. + */ +InMemoryBTree.Tree.prototype._updateRootNode = function(node) { + // dummy implementation; + // no-op return node; - }; - +}; - /** - * search - * - * Retrieves the node matching the given value. - * If no node is found, null is returned. - */ - WebLocalStorageBTree.Tree.prototype.search = function(key, checkExists) { +InMemoryBTree.Tree.prototype.clear = function() { + this.root = this._allocateNode(); + this.root.isLeaf = true; + this.root.level = 0; + this._updateRootNode(this.root); +}; + +/** + * search + * + * Retrieves the node matching the given value. + * If no node is found, null is returned. + */ +InMemoryBTree.Tree.prototype.search = function(key, checkExists) { var searching = true; - var node = this._diskRead(this.root); + var node = this.root; while(searching) { - var idx = 0; - while(idx < node.numberActives && this.comparator(key, node.keys[idx].key) === 1) { - idx++; - } - - if(idx < node.numberActives && this.comparator(node.keys[idx].key,key) === 0) { - if(checkExists != null && checkExists == true) { - return true; - } else { - return node.keys[idx].data; + var idx = 0; + while(idx < node.numberActives && this.comparator(key, node.keys[idx].key) === 1) { + idx++; } - } else { - if(node.isLeaf === true) { - searching = false; + + if(idx < node.numberActives && this.comparator(node.keys[idx].key,key) === 0) { + if(checkExists != null && checkExists == true) { + return true; + } else { + return node.keys[idx].data; + } } else { - node = this._diskRead(node.children[idx]); + if(node.isLeaf === true) { + searching = false; + } else { + node = this._diskRead(node.children[idx]); + } } - } } return null; - }; +}; - /** - * walk - * Applies a function to all the nodes key and data in the the - * tree in key order. - */ - WebLocalStorageBTree.Tree.prototype.walk = function(f) { - this._walk(f,this._diskRead(this.root)); - }; +/** + * walk + * Applies a function to all the nodes key and data in the the + * tree in key order. + */ +InMemoryBTree.Tree.prototype.walk = function(f) { + this._walk(f,this.root); +}; - WebLocalStorageBTree.Tree.prototype._walk = function(f,node) { +InMemoryBTree.Tree.prototype._walk = function(f,node) { if(node.isLeaf) { - for(var i=0; iindex+1; i--) { - parent.children[i] = parent.children[i-1]; + parent.children[i] = parent.children[i-1]; } - this._diskWrite(newChild); - parent.children[index+1] = newChild.pointer; + parent.children[index+1] = newChild; for(i = parent.numberActives; i>index; i--) { - parent.keys[i] = parent.keys[i-1]; + parent.keys[i] = parent.keys[i-1]; } parent.keys[index] = newParentChild; parent.numberActives++; + this._diskWrite(newChild); this._diskWrite(parent); this._diskWrite(child); - }; - - /** - * insert - * - * Creates a new node with value key and data and inserts it - * into the tree. - */ - WebLocalStorageBTree.Tree.prototype.insert = function(key,data) { - var currentRoot = this._diskRead(this.root); - - - if(currentRoot.numberActives === (2 * this.order - 1)) { - var newRoot = this._allocateNode(); - newRoot.isLeaf = false; - newRoot.level = currentRoot.level + 1; - newRoot.numberActives = 0; - newRoot.children[0] = currentRoot.pointer; - this._diskWrite(newRoot); - - this._splitChild(newRoot, 0, currentRoot); - this.root = newRoot.pointer; - this._updateRootNode(newRoot); - this._insertNonFull(newRoot, key, data); +}; + +/** + * insert + * + * Creates a new node with value key and data and inserts it + * into the tree. + */ +InMemoryBTree.Tree.prototype.insert = function(key,data) { + if(this.root.numberActives === (2 * this.order - 1)) { + var newRoot = this._allocateNode(); + newRoot.isLeaf = false; + newRoot.level = this.root.level + 1; + newRoot.numberActives = 0; + newRoot.children[0] = this.root; + + this._splitChild(newRoot, 0, this.root); + this.root = newRoot; + this._updateRootNode(this.root); + this._insertNonFull(newRoot, key, data); } else { - this._insertNonFull(currentRoot, key, data); - } - }; - - /** - * _insertNonFull - * - * Recursive function that tries to insert the new key in - * in the prvided node, or splits it and go deeper - * in the BTree hierarchy. - */ - WebLocalStorageBTree.Tree.prototype._insertNonFull = function(node,key,data) { + this._insertNonFull(this.root, key, data); + } +}; + +/** + * _insertNonFull + * + * Recursive function that tries to insert the new key in + * in the prvided node, or splits it and go deeper + * in the BTree hierarchy. + */ +InMemoryBTree.Tree.prototype._insertNonFull = function(node,key,data) { var idx = node.numberActives - 1; while(!node.isLeaf) { - while(idx>=0 && this.comparator(key,node.keys[idx].key) === -1) { - idx--; - } - idx++; - - var child = this._diskRead(node.children[idx]); + while(idx>=0 && this.comparator(key,node.keys[idx].key) === -1) { + idx--; + } + idx++; + var child = this._diskRead(node.children[idx]); - if(child.numberActives === 2*this.order -1) { - this._splitChild(node,idx,child); - if(this.comparator(key, node.keys[idx].key)===1) { - idx++; + if(child.numberActives === 2*this.order -1) { + this._splitChild(node,idx,child); + if(this.comparator(key, node.keys[idx].key)===1) { + idx++; + } } - } - node = this._diskRead(node.children[idx]); - idx = node.numberActives -1; + node = this._diskRead(node.children[idx]); + idx = node.numberActives -1; } while(idx>=0 && this.comparator(key,node.keys[idx].key) === -1) { - node.keys[idx+1] = node.keys[idx]; - idx--; + node.keys[idx+1] = node.keys[idx]; + idx--; } node.keys[idx + 1] = {key:key, data:data}; node.numberActives++; this._diskWrite(node); - }; - - /** - * delete - * - * Deletes the key from the BTree. - * If the key is not found, an exception is thrown. - * - * @param key the key to be deleted - * @returns true if the key is deleted false otherwise - */ - WebLocalStorageBTree.Tree.prototype['delete'] = function(key) { - var node = this._diskRead(this.root); +}; + +/** + * delete + * + * Deletes the key from the BTree. + * If the key is not found, an exception is thrown. + * + * @param key the key to be deleted + * @returns true if the key is deleted false otherwise + */ +InMemoryBTree.Tree.prototype['delete'] = function(key) { + var node = this.root; var parent = null; var searching = true; var idx = null; @@ -919,136 +770,132 @@ var shouldContinue = true; while(shouldContinue === true) { - shouldContinue = false; - while(searching === true) { - i = 0; + shouldContinue = false; - if(node.numberActives === 0) { - return false; - } - - while(i (this.order-1)) { - // The current node has (t - 1) keys but the right sibling has > (t - 1) keys - this._moveKey(parent,i,left); - node = this._diskRead(node.pointer); - } else if(lsibling != null && lsibling.numberActives > (this.order-1)) { - // The current node has (t - 1) keys but the left sibling has > (t - 1) keys - this._moveKey(parent,i,right); - node = this._diskRead(node.pointer); - } else if(lsibling != null && lsibling.numberActives === (this.order-1)) { - // The current node has (t - 1) keys but the left sibling has (t - 1) keys - node = this._mergeSiblings(parent,i,left); - } else if(rsibling != null && rsibling.numberActives === (this.order-1)){ - // The current node has (t - 1) keys but the left sibling has (t - 1) keys - node = this._mergeSiblings(parent,i,right); + if(idx === parent.numberActives) { + lsibling = this._diskRead(parent.children[idx-1]); + rsibling = null; + } else if(idx === 0) { + lsibling = null; + rsibling = this._diskRead(parent.children[1]); + } else { + lsibling = this._diskRead(parent.children[idx-1]); + rsibling = this._diskRead(parent.children[idx+1]); + } + + + if(node.numberActives === (this.order-1) && parent != null) { + if(rsibling != null && rsibling.numberActives > (this.order-1)) { + // The current node has (t - 1) keys but the right sibling has > (t - 1) keys + this._moveKey(parent,i,left); + } else if(lsibling != null && lsibling.numberActives > (this.order-1)) { + // The current node has (t - 1) keys but the left sibling has > (t - 1) keys + this._moveKey(parent,i,right); + } else if(lsibling != null && lsibling.numberActives === (this.order-1)) { + // The current node has (t - 1) keys but the left sibling has (t - 1) keys + node = this._mergeSiblings(parent,i,left); + } else if(rsibling != null && rsibling.numberActives === (this.order-1)){ + // The current node has (t - 1) keys but the left sibling has (t - 1) keys + node = this._mergeSiblings(parent,i,right); + } + } } - } } - } - //Case 1 : The node containing the key is found and is the leaf node. - //Also the leaf node has keys greater than the minimum required. - //Simply remove the key - if(node.isLeaf && (node.numberActives > (this.order-1))) { - this._deleteKeyFromNode(node,idx); - return true; - } + + //Case 1 : The node containing the key is found and is the leaf node. + //Also the leaf node has keys greater than the minimum required. + //Simply remove the key + if(node.isLeaf && (node.numberActives > (this.order-1))) { + this._deleteKeyFromNode(node,idx); + return true; + } - //If the leaf node is the root permit deletion even if the number of keys is - //less than (t - 1) - if(node.isLeaf && (node.pointer === this.root)) { - this._deleteKeyFromNode(node,idx); - return true; - } + //If the leaf node is the root permit deletion even if the number of keys is + //less than (t - 1) + if(node.isLeaf && (node === this.root)) { + this._deleteKeyFromNode(node,idx); + return true; + } + - try { //Case 2: The node containing the key is found and is an internal node if(node.isLeaf === false) { - var tmpNode = null; - var tmpNode2 = null; + var tmpNode = null; + var tmpNode2 = null; + if((tmpNode=this._diskRead(node.children[idx])).numberActives > (this.order-1)) { + var subNodeIdx = this._getMaxKeyPos(tmpNode); + key = subNodeIdx.node.keys[subNodeIdx.index]; - if((tmpNode=this._diskRead(node.children[idx])).numberActives > (this.order-1)) { - var subNodeIdx = this._getMaxKeyPos(tmpNode); - key = subNodeIdx.node.keys[subNodeIdx.index]; + node.keys[idx] = key; - node.keys[idx] = key; - - //this._delete(node.children[idx],key.key); - this._diskWrite(node); - node = tmpNode; - key = key.key; - shouldContinue = true; - searching = true; - } else { - if ((tmpNode = this._diskRead(node.children[idx+1])).numberActives >(this.order-1)) { - var subNodeIdx = this._getMinKeyPos(tmpNode); - key = subNodeIdx.node.keys[subNodeIdx.index]; + //this._delete(node.children[idx],key.key); + this._diskWrite(node); + node = tmpNode; + key = key.key; + shouldContinue = true; + searching = true; + } else if ((tmpNode = this._diskRead(node.children[idx+1])).numberActives >(this.order-1)) { + var subNodeIdx = this._getMinKeyPos(tmpNode); + key = subNodeIdx.node.keys[subNodeIdx.index]; - node.keys[idx] = key; + node.keys[idx] = key; - //this._delete(node.children[idx+1],key.key); - this._diskWrite(node); - node = tmpNode; - key = key.key; - shouldContinue = true; - searching = true; - } else { - if((tmpNode = this._diskRead(node.children[idx])).numberActives === (this.order-1) && - (tmpNode2 = this._diskRead(node.children[idx+1])).numberActives === (this.order-1)) { + //this._delete(node.children[idx+1],key.key); + this._diskWrite(node); + node = tmpNode; + key = key.key; + shouldContinue = true; + searching = true; + } else if((tmpNode = this._diskRead(node.children[idx])).numberActives === (this.order-1) && + (tmpNode2 = this._diskRead(node.children[idx+1])).numberActives === (this.order-1)) { var combNode = this._mergeNodes(tmpNode, node.keys[idx], tmpNode2); - node.children[idx] = combNode.pointer; + node.children[idx] = combNode; idx++; for(var i=idx; i this.order - 1) && searching===false) { - this._deleteKeyFromNode(node,idx); - } + // Case 3: + // In this case start from the top of the tree and continue + // moving to the leaf node making sure that each node that + // we encounter on the way has atleast 't' (order of the tree) + // keys + if(node.isLeaf && (node.numberActives > this.order - 1) && searching===false) { + this._deleteKeyFromNode(node,idx); + } - if(shouldContinue === false) { - return true; - } + if(shouldContinue === false) { + return true; + } } - }; +}; - /** - * _moveKey - * - * Move key situated at position i of the parent node - * to the left or right child at positions i-1 and i+1 - * according to the provided position - * - * @param parent the node whose is going to be moved to a child - * @param i Index of the key in the parent - * @param position left, or right - */ - WebLocalStorageBTree.Tree.prototype._moveKey = function (parent, i, position) { +/** + * _moveKey + * + * Move key situated at position i of the parent node + * to the left or right child at positions i-1 and i+1 + * according to the provided position + * + * @param parent the node whose is going to be moved to a child + * @param i Index of the key in the parent + * @param position left, or right + */ +InMemoryBTree.Tree.prototype._moveKey = function (parent, i, position) { if (position === right) { - i--; + i--; } //var lchild = parent.children[i-1]; @@ -1104,63 +945,63 @@ if (position == left) { - lchild.keys[lchild.numberActives] = parent.keys[i]; - lchild.children[lchild.numberActives + 1] = rchild.children[0]; - rchild.children[0] = null; - lchild.numberActives++; + lchild.keys[lchild.numberActives] = parent.keys[i]; + lchild.children[lchild.numberActives + 1] = rchild.children[0]; + rchild.children[0] = null; + lchild.numberActives++; - parent.keys[i] = rchild.keys[0]; + parent.keys[i] = rchild.keys[0]; - for (var _i = 1; _i < rchild.numberActives; _i++) { - rchild.keys[_i - 1] = rchild.keys[_i]; - rchild.children[_i - 1] = rchild.children[_i]; - } - rchild.children[rchild.numberActives - 1] = rchild.children[rchild.numberActives]; - rchild.numberActives--; + for (var _i = 1; _i < rchild.numberActives; _i++) { + rchild.keys[_i - 1] = rchild.keys[_i]; + rchild.children[_i - 1] = rchild.children[_i]; + } + rchild.children[rchild.numberActives - 1] = rchild.children[rchild.numberActives]; + rchild.numberActives--; } else { - rchild.children[rchild.numberActives + 1] = rchild.children[rchild.numberActives]; - for (var _i = rchild.numberActives; _i > 0; _i--) { - rchild.children[_i] = rchild.children[_i - 1]; - rchild.keys[_i] = rchild.keys[_i - 1]; - } - rchild.keys[0] = null; - rchild.children[0] = null; + rchild.children[rchild.numberActives + 1] = rchild.children[rchild.numberActives]; + for (var _i = rchild.numberActives; _i > 0; _i--) { + rchild.children[_i] = rchild.children[_i - 1]; + rchild.keys[_i] = rchild.keys[_i - 1]; + } + rchild.keys[0] = null; + rchild.children[0] = null; - rchild.children[0] = lchild.children[lchild.numberActives]; - rchild.keys[0] = parent.keys[i]; - rchild.numberActives++; + rchild.children[0] = lchild.children[lchild.numberActives]; + rchild.keys[0] = parent.keys[i]; + rchild.numberActives++; - lchild.children[lchild.numberActives] = null; - parent.keys[i] = lchild.keys[lchild.numberActives - 1]; - lchild.keys[lchild.numberActives - 1] = null; - lchild.numberActives--; + lchild.children[lchild.numberActives] = null; + parent.keys[i] = lchild.keys[lchild.numberActives - 1]; + lchild.keys[lchild.numberActives - 1] = null; + lchild.numberActives--; } this._diskWrite(lchild); this._diskWrite(rchild); this._diskWrite(parent); - }; - - /** - * _mergeSiblings - * - * Merges two nodes at the left and right of the provided - * index in the parent node. - * - * @param parent the node whose children will be merged - * @param i Index of the key in the parent pointing to the nodes to merge - */ - WebLocalStorageBTree.Tree.prototype._mergeSiblings = function (parent, index, pos) { +}; + +/** + * _mergeSiblings + * + * Merges two nodes at the left and right of the provided + * index in the parent node. + * + * @param parent the node whose children will be merged + * @param i Index of the key in the parent pointing to the nodes to merge + */ +InMemoryBTree.Tree.prototype._mergeSiblings = function (parent, index, pos) { var i, j; var n1, n2; if (index === (parent.numberActives)) { - index--; - n1 = this._diskRead(parent.children[parent.numberActives - 1]); - n2 = this._diskRead(parent.children[parent.numberActives]); + index--; + n1 = this._diskRead(parent.children[parent.numberActives - 1]); + n2 = this._diskRead(parent.children[parent.numberActives]); } else { - n1 = this._diskRead(parent.children[index]); - n2 = this._diskRead(parent.children[index + 1]); + n1 = this._diskRead(parent.children[index]); + n2 = this._diskRead(parent.children[index + 1]); } //Merge the current node with the left node @@ -1169,92 +1010,92 @@ newNode.level = n1.level; for (j = 0; j < this.order - 1; j++) { - newNode.keys[j] = n1.keys[j]; - newNode.children[j] = n1.children[j]; + newNode.keys[j] = n1.keys[j]; + newNode.children[j] = n1.children[j]; } newNode.keys[this.order - 1] = parent.keys[index]; newNode.children[this.order - 1] = n1.children[this.order - 1]; for (j = 0; j < this.order - 1; j++) { - newNode.keys[j + this.order] = n2.keys[j]; - newNode.children[j + this.order] = n2.children[j]; + newNode.keys[j + this.order] = n2.keys[j]; + newNode.children[j + this.order] = n2.children[j]; } newNode.children[2 * this.order - 1] = n2.children[this.order - 1]; - this._diskWrite(newNode); - parent.children[index] = newNode.pointer; + parent.children[index] = newNode; for (j = index; j < parent.numberActives; j++) { - parent.keys[j] = parent.keys[j + 1]; - parent.children[j + 1] = parent.children[j + 2]; + parent.keys[j] = parent.keys[j + 1]; + parent.children[j + 1] = parent.children[j + 2]; } newNode.numberActives = n1.numberActives + n2.numberActives + 1; parent.numberActives--; for (i = parent.numberActives; i < 2 * this.order - 1; i++) { - parent.keys[i] = null; + parent.keys[i] = null; } - if (parent.numberActives === 0 && this.root === parent.pointer) { - this.root = newNode.pointer; - if (newNode.level) { - newNode.isLeaf = false; - } else { - newNode.isLeaf = true; - } + if (parent.numberActives === 0 && this.root === parent) { + this.root = newNode; + if (newNode.level) { + newNode.isLeaf = false; + } else { + newNode.isLeaf = true; + } } this._diskWrite(newNode); - if (this.root === newNode.pointer) { - this._updateRootNode(newNode); + if (this.root === newNode) { + this._updateRootNode(this.root); } this._diskWrite(parent); this._diskDelete(n1); this._diskDelete(n2); return newNode; - }; - - /** - * _deleteKeyFromNode - * - * Deletes the key at position index from the provided node. - * - * @param node The node where the key will be deleted. - * @param index The index of the key that will be deletd. - * @return true if the key can be deleted, false otherwise - */ - WebLocalStorageBTree.Tree.prototype._deleteKeyFromNode = function (node, index) { +}; + +/** + * _deleteKeyFromNode + * + * Deletes the key at position index from the provided node. + * + * @param node The node where the key will be deleted. + * @param index The index of the key that will be deletd. + * @return true if the key can be deleted, false otherwise + */ +InMemoryBTree.Tree.prototype._deleteKeyFromNode = function (node, index) { var keysMax = (2 * this.order) - 1; if (node.numberActives < keysMax) { - keysMax = node.numberActives; + keysMax = node.numberActives; } ; var i; if (node.isLeaf === false) { - return false; + return false; } var key = node.keys[index]; for (i = index; i < keysMax - 1; i++) { - node.keys[i] = node.keys[i + 1]; + node.keys[i] = node.keys[i + 1]; } // cleaning invalid reference - node.keys.splice(keysMax - 1, (node.keys.length - (keysMax - 1))); + node.keys.pop(); + node.numberActives--; this._diskWrite(node); return true; - }; +}; - WebLocalStorageBTree.Tree.prototype._mergeNodes = function (n1, key, n2) { +InMemoryBTree.Tree.prototype._mergeNodes = function (n1, key, n2) { var newNode; var i; @@ -1262,15 +1103,15 @@ newNode.isLeaf = true; for (i = 0; i < n1.numberActives; i++) { - newNode.keys[i] = n1.keys[i]; - newNode.children[i] = n1.children[i]; + newNode.keys[i] = n1.keys[i]; + newNode.children[i] = n1.children[i]; } newNode.children[n1.numberActives] = n1.children[n1.numberActives]; newNode.keys[n1.numberActives] = key; for (i = 0; i < n2.numberActives; i++) { - newNode.keys[i + n1.numberActives + 1] = n2.keys[i]; - newNode.children[i + n1.numberActives + 1] = n2.children[i]; + newNode.keys[i + n1.numberActives + 1] = n2.keys[i]; + newNode.children[i + n1.numberActives + 1] = n2.children[i]; } newNode.children[(2 * this.order) - 1] = n2.children[n2.numberActives]; @@ -1280,509 +1121,247 @@ this._diskWrite(newNode); - this._diskDelete(n1); - this._diskDelete(n2); // @todo // delte old nodes from disk return newNode; - }; - - /** - * audit - * - * Checks that the tree data structure is - * valid. - */ - WebLocalStorageBTree.Tree.prototype.audit = function (showOutput) { +}; + +/** + * audit + * + * Checks that the tree data structure is + * valid. + */ +InMemoryBTree.Tree.prototype.audit = function (showOutput) { var errors = []; var alreadySeen = []; var that = this; var foundInArray = function (data) { - for (var i = 0; i < alreadySeen.length; i++) { - if (that.comparator(alreadySeen[i], data) === 0) { - var error = " !!! duplicated key " + data; - if (showOutput === true) { - console.log(error); - } - errors.push(error); + for (var i = 0; i < alreadySeen.length; i++) { + if (that.comparator(alreadySeen[i], data) === 0) { + var error = " !!! duplicated key " + data; + if (showOutput === true) { + console.log(error); + } + errors.push(error); + } } - } }; var length = null; var that = this; this.walkNodes(function (n) { - if (showOutput === true) { - console.log("--- Node at " + n.level + " level"); - console.log(" - pointer: " + n.pointer); - console.log(" - leaf? " + n.isLeaf); - console.log(" - num actives? " + n.numberActives); - console.log(" - keys: "); - } - for (var i = n.numberActives; i < n.keys.length; i++) { - if (n.keys[i] != null) { - if (showOutput === true) { - console.log(" * warning : redundant key data"); - errors.push(" * warning : redundant key data"); - } + if (showOutput === true) { + console.log("--- Node at " + n.level + " level"); + console.log(" - leaf? " + n.isLeaf); + console.log(" - num actives? " + n.numberActives); + console.log(" - keys: "); + } + for (var i = n.numberActives; i < n.keys.length; i++) { + if (n.keys[i] != null) { + if (showOutput === true) { + console.log(" * warning : redundant key data"); + errors.push(" * warning : redundant key data"); + } + } } - } - for (var i = n.numberActives + 1; i < n.children.length; i++) { - if (n.children[i] != null) { - if (showOutput === true) { - console.log(" * warning : redundant children data"); - errors.push(" * warning : redundant key data"); - } + for (var i = n.numberActives + 1; i < n.children.length; i++) { + if (n.children[i] != null) { + if (showOutput === true) { + console.log(" * warning : redundant children data"); + errors.push(" * warning : redundant key data"); + } + } } - } - if (n.isLeaf === false) { - for (var i = 0; i < n.numberActives; i++) { - var maxLeft = that._diskRead(n.children[i]).keys[that._diskRead(n.children[i]).numberActives - 1 ].key; - var minRight = that._diskRead(n.children[i + 1]).keys[0].key; - if (showOutput === true) { - console.log(" " + n.keys[i].key + "(" + maxLeft + "," + minRight + ")"); - } - if (that.comparator(n.keys[i].key, maxLeft) === -1) { - var error = " !!! value max left " + maxLeft + " > key " + n.keys[i].key; - if (showOutput === true) { - console.log(error); + if (n.isLeaf === false) { + for (var i = 0; i < n.numberActives; i++) { + var maxLeft = that._diskRead(n.children[i]).keys[that._diskRead(n.children[i]).numberActives - 1 ].key; + var minRight = that._diskRead(n.children[i + 1]).keys[0].key; + if (showOutput === true) { + console.log(" " + n.keys[i].key + "(" + maxLeft + "," + minRight + ")"); + } + if (that.comparator(n.keys[i].key, maxLeft) === -1) { + var error = " !!! value max left " + maxLeft + " > key " + n.keys[i].key; + if (showOutput === true) { + console.log(error); + } + errors.push(error); + } + if (that.comparator(n.keys[i].key, minRight) === 1) { + var error = " !!! value min right " + minRight + " < key " + n.keys[i].key; + if (showOutput === true) { + console.log(error); + } + errors.push(error); + } + + foundInArray(n.keys[i].key); + alreadySeen.push(n.keys[i].key); } - errors.push(error); - } - if (that.comparator(n.keys[i].key, minRight) === 1) { - var error = " !!! value min right " + minRight + " < key " + n.keys[i].key; - if (showOutput === true) { - console.log(error); + } else { + if (length === null) { + length = n.level; + } else { + if (length != n.level) { + var error = " !!! Leaf node with wrong level value"; + if (showOutput === true) { + console.log(error); + } + errors.push(error); + } } - errors.push(error); - } + for (var i = 0; i < n.numberActives; i++) { + if (showOutput === true) { + console.log(" " + n.keys[i].key); + } + foundInArray(n.keys[i].key); + alreadySeen.push(n.keys[i].key); - foundInArray(n.keys[i].key); - alreadySeen.push(n.keys[i].key); - } - } else { - if (length === null) { - length = n.level; - } else { - if (length != n.level) { - var error = " !!! Leaf node with wrong level value"; - if (showOutput === true) { - console.log(error); } - errors.push(error); - } } - for (var i = 0; i < n.numberActives; i++) { - if (showOutput === true) { - console.log(" " + n.keys[i].key); - } - foundInArray(n.keys[i].key); - alreadySeen.push(n.keys[i].key); - } - } + if (n != that.root) { + if (n.numberActives > ((2 * that.order) - 1)) { + if (showOutput === true) { + var error = " !!!! MAX num keys restriction violated "; + } + console.log(error); + errors.push(error); + } + if (n.numberActives < (that.order - 1)) { + if (showOutput === true) { + var error = " !!!! MIN num keys restriction violated "; + } + console.log(error); + errors.push(error); + } - if (n.pointer != that.root) { - if (n.numberActives > ((2 * that.order) - 1)) { - if (showOutput === true) { - var error = " !!!! MAX num keys restriction violated "; - } - console.log(error); - errors.push(error); - } - if (n.numberActives < (that.order - 1)) { - if (showOutput === true) { - var error = " !!!! MIN num keys restriction violated "; - } - console.log(error); - errors.push(error); } - - } }); return errors; - }; - - WebLocalStorageBTree.Tree.prototype.clear = function () { - this.diskManager.clear(); - this.root = this._allocateNode(); - this.root.isLeaf = true; - this.root.level = 0; - this._diskWrite(this.root); - this._updateRootNode(this.root); - this.root = this.root.pointer; - }; - - /** - * _getMaxKeyPos - * - * Used to get the position of the MAX key within the subtree - * @return An object containing the key and position of the key - */ - WebLocalStorageBTree.Tree.prototype._getMaxKeyPos = function (node) { +}; + +/** + * _getMaxKeyPos + * + * Used to get the position of the MAX key within the subtree + * @return An object containing the key and position of the key + */ +InMemoryBTree.Tree.prototype._getMaxKeyPos = function (node) { var node_pos = {}; while (true) { - if (node === null) { - break; - } + if (node === null) { + break; + } - if (node.isLeaf === true) { - node_pos.node = node; - node_pos.index = node.numberActives - 1; - return node_pos; - } else { - node_pos.node = node; - node_pos.index = node.numberActives - 1; - node = this._diskRead(node.children[node.numberActives]); - } + if (node.isLeaf === true) { + node_pos.node = node; + node_pos.index = node.numberActives - 1; + return node_pos; + } else { + node_pos.node = node; + node_pos.index = node.numberActives - 1; + node = this._diskRead(node.children[node.numberActives]); + } } return node_pos; - }; - - /** - * _getMinKeyPos - * - * Used to get the position of the MAX key within the subtree - * @return An object containing the key and position of the key - */ - WebLocalStorageBTree.Tree.prototype._getMinKeyPos = function (node) { +}; + +/** + * _getMinKeyPos + * + * Used to get the position of the MAX key within the subtree + * @return An object containing the key and position of the key + */ +InMemoryBTree.Tree.prototype._getMinKeyPos = function (node) { var node_pos = {}; while (true) { - if (node === null) { - break; - } + if (node === null) { + break; + } - if (node.isLeaf === true) { - node_pos.node = node; - node_pos.index = 0; - return node_pos; - } else { - node_pos.node = node; - node_pos.index = 0; - node = this._diskRead(node.children[0]); - } + if (node.isLeaf === true) { + node_pos.node = node; + node_pos.index = 0; + return node_pos; + } else { + node_pos.node = node; + node_pos.index = 0; + node = this._diskRead(node.children[0]); + } } return node_pos; - }; - - - /** - * Node - * - * Implements the interface of BinarySearchTree.Node - * - * A Tree node augmented with BTree - * node structures - */ - WebLocalStorageBTree.Node = function() { +}; + + +/** + * Node + * + * Implements the interface of BinarySearchTree.Node + * + * A Tree node augmented with BTree + * node structures + */ +InMemoryBTree.Node = function() { this.numberActives = 0; this.isLeaf = null; this.keys = []; this.children = []; this.level = 0; - }; - - /** - * LocalStorageManager - * - * Handle read/writes in the local storage object. - * In this implementation the pointers are just the keys in - * the local storage object. - */ - WebLocalStorageBTree.LocalStorageManager = function(name,storage, maxSize) { - this.name = name; - this.storage = storage; - this.maxSize = maxSize; - this.bufferCache = new PriorityQueue.PriorityQueue({"maxSize": maxSize}); - this.counter = this.storage.getItem("__"+this.name+"__ID_COUNTER__") || 0; - }; +}; - /** - * Cleans all data in the local storage - */ - WebLocalStorageBTree.LocalStorageManager.prototype.clear = function() { - var localStorageLength = this.storage.length; - var keysToDelete = []; - - for(var i=0; i> "+encodedNode); - var node = new WebLocalStorageBTree.Node(); - var parts = encodedNode.split(":"); - - //encoded = ""+node.numberActives; - node.numberActives = parseInt(parts[0]); - //encoded = encoded+":"+node.pointer; - node.pointer = parts[1]; - //encoded = encoded+":"+node.level; - node.level = parseInt(parts[2]); - //encoded = encoded+":"+(node.isLeaf ? 1 : 0); - if(parts[3] === '1') { - node.isLeaf = true; - } else { - node.isLeaf = false; - } - - var numKeys = parseInt(parts[4]); - var counter = 5; - var key, type, data; - for(var i=0; i> "); - //console.log(node); - return node; - }; - - -// end of ./src/js-trees/src/web_local_storage_b_tree.js +// end of ./src/js-trees/src/in_memory_b_tree.js // exports - var QuadIndexCommon = {}; - - /** - * NodeKey - * - * Implements the interface of BinarySearchTree.Node - * - * A Tree node augmented with BPlusTree - * node structures - */ - QuadIndexCommon.NodeKey = function(components, order) { +var QuadIndexCommon = {}; + +/** + * NodeKey + * + * Implements the interface of BinarySearchTree.Node + * + * A Tree node augmented with BPlusTree + * node structures + */ +QuadIndexCommon.NodeKey = function(components, order) { this.subject = components.subject; this.predicate = components.predicate; this.object = components.object; this.graph = components.graph; this.order = order; - }; +}; - QuadIndexCommon.NodeKey.prototype.comparator = function(keyPattern) { +QuadIndexCommon.NodeKey.prototype.comparator = function(keyPattern) { for(var i=0; i keyPattern[component]) { - return 1 + var component = this.order[i]; + if(keyPattern[component] == null) { + return 0; + } else { + if(this[component] < keyPattern[component] ) { + return -1 + } else if(this[component] > keyPattern[component]) { + return 1 + } } - } } return 0; - }; - - /** - * Pattern - * - * A pattern with some variable components - */ - QuadIndexCommon.Pattern = function (components) { +}; + +/** + * Pattern + * + * A pattern with some variable components + */ +QuadIndexCommon.Pattern = function (components) { this.subject = components.subject; this.predicate = components.predicate; this.object = components.object; @@ -1800,305 +1379,282 @@ // OIDs retrieved from the lexicon *are* numbers so // they can be told apart from variables (strings) for (var i = 0; i < components.length; i++) { - if (typeof(this[components[i]]) === 'string') { - indif.push(components[i]); - this.keyComponents[components[i]] = null; - } else { - order.push(components[i]); - this.keyComponents[components[i]] = this[components[i]]; - this.indexKey.push(components[i]); - } + if (typeof(this[components[i]]) === 'string') { + indif.push(components[i]); + this.keyComponents[components[i]] = null; + } else { + order.push(components[i]); + this.keyComponents[components[i]] = this[components[i]]; + this.indexKey.push(components[i]); + } } this.order = order.concat(indif); this.key = new QuadIndexCommon.NodeKey(this.keyComponents, this.order); - }; +}; // end of ./src/js-rdf-persistence/src/quad_index_common.js // exports - var QuadIndex = {}; +var QuadIndex = {}; // imports - var BaseTree = WebLocalStorageBTree; - QuadIndex.Tree = function(params,callback) { - if(arguments != 0) { - this.componentOrder = params.componentOrder; +var BaseTree = InMemoryBTree; +QuadIndex.Tree = function(params,callback) { + if(arguments != 0) { + this.componentOrder = params.componentOrder; - // @todo change this if using the file backed implementation - BaseTree.Tree.call(this, params.order, params['name'], params['persistent'], params['cacheMaxSize']); - this.comparator = function (a, b) { - for (var i = 0; i < this.componentOrder.length; i++) { - var component = this.componentOrder[i]; - var vala = a[component]; - var valb = b[component]; - if (vala < valb) { - return -1; - } else if (vala > valb) { - return 1; - } - } - return 0; - }; + // @todo change this if using the file backed implementation + BaseTree.Tree.call(this, params.order, params['name'], params['persistent'], params['cacheMaxSize']); - this.rangeComparator = function (a, b) { - for (var i = 0; i < this.componentOrder.length; i++) { - var component = this.componentOrder[i]; - if (b[component] == null || a[component] == null) { + this.comparator = function (a, b) { + for (var i = 0; i < this.componentOrder.length; i++) { + var component = this.componentOrder[i]; + var vala = a[component]; + var valb = b[component]; + if (vala < valb) { + return -1; + } else if (vala > valb) { + return 1; + } + } return 0; - } else { - if (a[component] < b[component]) { - return -1 - } else if (a[component] > b[component]) { - return 1 + }; + + this.rangeComparator = function (a, b) { + for (var i = 0; i < this.componentOrder.length; i++) { + var component = this.componentOrder[i]; + if (b[component] == null || a[component] == null) { + return 0; + } else { + if (a[component] < b[component]) { + return -1 + } else if (a[component] > b[component]) { + return 1 + } + } } - } - } - return 0; - }; + return 0; + }; - if(callback!=null) { - callback(this); - } + if(callback!=null) { + callback(this); + } } - }; +}; - Utils['extends'](BaseTree.Tree, QuadIndex.Tree); +Utils['extends'](BaseTree.Tree, QuadIndex.Tree); - QuadIndex.Tree.prototype.insert = function(quad, callback) { +QuadIndex.Tree.prototype.insert = function(quad, callback) { BaseTree.Tree.prototype.insert.call(this, quad, null); if(callback) - callback(true); + callback(true); return true - }; +}; - QuadIndex.Tree.prototype.search = function(quad, callback) { +QuadIndex.Tree.prototype.search = function(quad, callback) { var result = BaseTree.Tree.prototype.search.call(this, quad, true); // true -> check exists : not present in all the b-tree implementations, check first. if(callback) - callback(result); + callback(result); return result; - }; +}; - QuadIndex.Tree.prototype.range = function (pattern, callback) { +QuadIndex.Tree.prototype.range = function (pattern, callback) { var result = null; if (typeof(this.root) === 'string') { - result = this._rangeTraverse(this, this._diskRead(this.root), pattern); + result = this._rangeTraverse(this, this._diskRead(this.root), pattern); } else { - result = this._rangeTraverse(this, this.root, pattern); + result = this._rangeTraverse(this, this.root, pattern); } if (callback) - callback(result); + callback(result); return result; - }; +}; - QuadIndex.Tree.prototype._rangeTraverse = function(tree,node, pattern) { +QuadIndex.Tree.prototype._rangeTraverse = function(tree,node, pattern) { var patternKey = pattern.key; var acum = []; var pendingNodes = [node]; var node, idxMin, idxMax; while(pendingNodes.length > 0) { - node = pendingNodes.shift(); - idxMin = 0; - - while(idxMin < node.numberActives && tree.rangeComparator(node.keys[idxMin].key,patternKey) === -1) { - idxMin++; - } - if(node.isLeaf === true) { - idxMax = idxMin; + node = pendingNodes.shift(); + idxMin = 0; - while(idxMax < node.numberActives && tree.rangeComparator(node.keys[idxMax].key,patternKey) === 0) { - acum.push(node.keys[idxMax].key); - idxMax++; + while(idxMin < node.numberActives && tree.rangeComparator(node.keys[idxMin].key,patternKey) === -1) { + idxMin++; } + if(node.isLeaf === true) { + idxMax = idxMin; - } else { - var pointer = node.children[idxMin]; - var childNode = tree._diskRead(pointer); - pendingNodes.push(childNode); - - var idxMax = idxMin; - while(true) { - if(idxMax < node.numberActives && tree.rangeComparator(node.keys[idxMax].key,patternKey) === 0) { - acum.push(node.keys[idxMax].key); - idxMax++; - childNode = tree._diskRead(node.children[idxMax]); + while(idxMax < node.numberActives && tree.rangeComparator(node.keys[idxMax].key,patternKey) === 0) { + acum.push(node.keys[idxMax].key); + idxMax++; + } + + } else { + var pointer = node.children[idxMin]; + var childNode = tree._diskRead(pointer); pendingNodes.push(childNode); - } else { - break; - } + + var idxMax = idxMin; + while(true) { + if(idxMax < node.numberActives && tree.rangeComparator(node.keys[idxMax].key,patternKey) === 0) { + acum.push(node.keys[idxMax].key); + idxMax++; + childNode = tree._diskRead(node.children[idxMax]); + pendingNodes.push(childNode); + } else { + break; + } + } } - } } return acum; - }; +}; // end of ./src/js-rdf-persistence/src/quad_index.js // exports - var QuadBackend = {}; +var QuadBackend = {}; // imports - /* - * "perfect" indices for RDF indexing - * - * SPOG (?, ?, ?, ?), (s, ?, ?, ?), (s, p, ?, ?), (s, p, o, ?), (s, p, o, g) - * GP (?, ?, ?, g), (?, p, ?, g) - * OGS (?, ?, o, ?), (?, ?, o, g), (s, ?, o, g) - * POG (?, p, ?, ?), (?, p, o, ?), (?, p, o, g) - * GSP (s, ?, ?, g), (s, p, ?, g) - * OS (s, ?, o, ?) - */ - QuadBackend.QuadBackend = function (configuration, callback) { +/* + * "perfect" indices for RDF indexing + * + * SPOG (?, ?, ?, ?), (s, ?, ?, ?), (s, p, ?, ?), (s, p, o, ?), (s, p, o, g) + * GP (?, ?, ?, g), (?, p, ?, g) + * OGS (?, ?, o, ?), (?, ?, o, g), (s, ?, o, g) + * POG (?, p, ?, ?), (?, p, o, ?), (?, p, o, g) + * GSP (s, ?, ?, g), (s, p, ?, g) + * OS (s, ?, o, ?) + */ +QuadBackend.QuadBackend = function (configuration, callback) { if (arguments != 0) { - this.indexMap = {}; - this.treeOrder = configuration['treeOrder']; - this.indices = ['SPOG', 'GP', 'OGS', 'POG', 'GSP', 'OS']; - this.componentOrders = { - SPOG:['subject', 'predicate', 'object', 'graph'], - GP:['graph', 'predicate', 'subject', 'object'], - OGS:['object', 'graph', 'subject', 'predicate'], - POG:['predicate', 'object', 'graph', 'subject'], - GSP:['graph', 'subject', 'predicate', 'object'], - OS:['object', 'subject', 'predicate', 'graph'] - }; + this.indexMap = {}; + this.treeOrder = configuration['treeOrder']; + this.indices = ['SPOG', 'GP', 'OGS', 'POG', 'GSP', 'OS']; + this.componentOrders = { + SPOG:['subject', 'predicate', 'object', 'graph'], + GP:['graph', 'predicate', 'subject', 'object'], + OGS:['object', 'graph', 'subject', 'predicate'], + POG:['predicate', 'object', 'graph', 'subject'], + GSP:['graph', 'subject', 'predicate', 'object'], + OS:['object', 'subject', 'predicate', 'graph'] + }; - for (var i = 0; i < this.indices.length; i++) { - var indexKey = this.indices[i]; - this.indexMap[indexKey] = new QuadIndex.Tree({order:this.treeOrder, - componentOrder:this.componentOrders[indexKey], - persistent:configuration['persistent'], - name:(configuration['name'] || "") + indexKey, - cacheMaxSize:configuration['cacheMaxSize']}); - } + for (var i = 0; i < this.indices.length; i++) { + var indexKey = this.indices[i]; + this.indexMap[indexKey] = new QuadIndex.Tree({order:this.treeOrder, + componentOrder:this.componentOrders[indexKey], + persistent:configuration['persistent'], + name:(configuration['name'] || "") + indexKey, + cacheMaxSize:configuration['cacheMaxSize']}); + } - if (callback) - callback(this); + if (callback) + callback(this); } - }; +}; - QuadBackend.QuadBackend.prototype.clear = function() { - for(var i=0; i') { - var value = literalString.substring(1,parts-1); - var type = literalString.substring(parts+3, literalString.length-1); + var value = literalString.substring(1,parts-1); + var type = literalString.substring(parts+3, literalString.length-1); - return {token: "literal", value:value, type:type}; + return {token: "literal", value:value, type:type}; } var value = literalString.substring(1,literalString.length-1); return {token:"literal", value:value}; - }; +}; - WebLocalStorageLexicon.Lexicon.prototype.parseUri = function(uriString) { +Lexicon.Lexicon.prototype.parseUri = function(uriString) { return {token: "uri", value:uriString}; - }; +}; - WebLocalStorageLexicon.Lexicon.prototype.retrieve = function(oid) { - var fromStorage; +Lexicon.Lexicon.prototype.retrieve = function(oid) { try { - if(oid === this.defaultGraphOid) { - return({ token: "uri", - value:this.defaultGraphUri, - prefix: null, - suffix: null, - defaultGraph: true }); - } else { - var maybeUri = this.OIDToUri['u'+oid]; - if(maybeUri!=null) { - return(this.parseUri(maybeUri)); + if(oid === this.defaultGraphOid) { + return({ token: "uri", + value:this.defaultGraphUri, + prefix: null, + suffix: null, + defaultGraph: true }); } else { - var maybeLiteral = this.OIDToLiteral['l'+oid]; - if(maybeLiteral!=null) { - return(this.parseLiteral(maybeLiteral)); + var maybeUri = this.OIDToUri['u'+oid]; + if(maybeUri != null) { + return(this.parseUri(maybeUri)); } else { - var maybeBlank = this.OIDToBlank[""+oid]; - if(maybeBlank!=null) { - return({token:"blank", value:"_:"+oid}); - } else { - // uri - maybeUri = this.storage.getItem(this.pointer("OIDToUri","u"+oid)); - if(maybeUri != null) { - this.OIDToUri["u"+oid] = maybeUri; - fromStorage = this.storage.getItem(this.pointer("uriToOID", maybeUri)); - var parts = fromStorage.split(":"); - var counter = parseInt(parts[1]); - this.uriToOID[maybeUri] = [oid,counter]; - return(this.parseUri(maybeUri)); - } else { - // literal - maybeLiteral = this.storage.getItem(this.pointer("OIDToLiteral","l"+oid)); - if(maybeLiteral != null) { - this.OIDToLiteral["l"+oid] = maybeLiteral; - fromStorage = this.storage.getItem(this.pointer("literalToOID",maybeLiteral)); - var oidCounter = fromStorage.split(":"); - var oid = parseInt(oidCounter[0]); - var counter = parseInt(oidCounter[1]); - this.literalToOID[maybeLiteral] = [oid, counter]; + var maybeLiteral = this.OIDToLiteral['l'+oid]; + if(maybeLiteral != null) { return(this.parseLiteral(maybeLiteral)); - } else { - // blank - maybeBlank = this.storage.getItem(this.pointer("OIDToBlank",""+oid)); + } else { + var maybeBlank = this.OIDToBlank[""+oid]; if(maybeBlank != null) { - this.OIDToBlank[""+oid] = true; - return({token:"blank", value:"_:"+oid}); + return({token:"blank", value:"_:"+oid}); } else { - throw("Null value for OID"); + throw("Null value for OID"); } - } } - } } } - } } catch(e) { - console.log("error in lexicon retrieving OID:"); - console.log(oid); - if(e.message) { - console.log(e.message); - } - if(e.stack) { - console.log(e.stack); - } - throw new Error("Unknown retrieving OID in lexicon:"+oid); + console.log("error in lexicon retrieving OID:"); + console.log(oid); + if(e.message || e.stack) { + if(e.message) { + console.log(e.message); + } + if(e.stack) { + console.log(e.stack); + } + } else { + console.log(e); + } + throw new Error("Unknown retrieving OID in lexicon:"+oid); } - }; +}; + +Lexicon.Lexicon.prototype.clear = function() { + this.uriToOID = {}; + this.OIDToUri = {}; + + this.literalToOID = {}; + this.OIDToLiteral = {}; + this.blankToOID = {}; + this.OIDToBlank = {}; +}; - WebLocalStorageLexicon.Lexicon.prototype.unregister = function (quad, key) { +Lexicon.Lexicon.prototype.unregister = function (quad, key) { try { - this.unregisterTerm(quad.subject.token, key.subject); - this.unregisterTerm(quad.predicate.token, key.predicate); - this.unregisterTerm(quad.object.token, key.object); - if (quad.graph != null) { - this.unregisterTerm(quad.graph.token, key.graph); - } - return(true); + this.unregisterTerm(quad.subject.token, key.subject); + this.unregisterTerm(quad.predicate.token, key.predicate); + this.unregisterTerm(quad.object.token, key.object); + if (quad.graph != null) { + this.unregisterTerm(quad.graph.token, key.graph); + } + return(true); } catch (e) { - console.log("Error unregistering quad"); - console.log(e.message); - return(false); + console.log("Error unregistering quad"); + console.log(e.message); + return(false); } - }; +}; - WebLocalStorageLexicon.Lexicon.prototype.unregisterTerm = function (kind, oid) { +Lexicon.Lexicon.prototype.unregisterTerm = function (kind, oid) { if (kind === 'uri') { - if (oid != this.defaultGraphOid) { - var oidStr = 'u' + oid; - var uri = this.OIDToUri[oidStr]; // = uri; - var oidCounter = this.uriToOID[uri]; // =[oid, 0]; - - var counter = oidCounter[1]; - if ("" + oidCounter[0] === "" + oid) { - if (counter === 0) { - delete this.OIDToUri[oidStr]; - delete this.uriToOID[uri]; - // delete the graph oid from known graphs - // in case this URI is a graph identifier - delete this.knownGraphs[oid]; - } else { - this.uriToOID[uri] = [oid, counter - 1]; - } - } else { - throw("Not matching OID : " + oid + " vs " + oidCounter[0]); + if (oid != this.defaultGraphOid) { + var oidStr = 'u' + oid; + var uri = this.OIDToUri[oidStr]; // = uri; + var oidCounter = this.uriToOID[uri]; // =[oid, 0]; + + var counter = oidCounter[1]; + if ("" + oidCounter[0] === "" + oid) { + if (counter === 0) { + delete this.OIDToUri[oidStr]; + delete this.uriToOID[uri]; + // delete the graph oid from known graphs + // in case this URI is a graph identifier + delete this.knownGraphs[oid]; + } else { + this.uriToOID[uri] = [oid, counter - 1]; + } + } else { + throw("Not matching OID : " + oid + " vs " + oidCounter[0]); + } } - } } else if (kind === 'literal') { - this.oidCounter++; - var oidStr = 'l' + oid; - var literal = this.OIDToLiteral[oidStr]; // = literal; - var oidCounter = this.literalToOID[literal]; // = [oid, 0]; + this.oidCounter++; + var oidStr = 'l' + oid; + var literal = this.OIDToLiteral[oidStr]; // = literal; + var oidCounter = this.literalToOID[literal]; // = [oid, 0]; - var counter = oidCounter[1]; - if ("" + oidCounter[0] === "" + oid) { - if (counter === 0) { - delete this.OIDToLiteral[oidStr]; - delete this.literalToOID[literal]; + var counter = oidCounter[1]; + if ("" + oidCounter[0] === "" + oid) { + if (counter === 0) { + delete this.OIDToLiteral[oidStr]; + delete this.literalToOID[literal]; + } else { + this.literalToOID[literal] = [oid, counter - 1]; + } } else { - this.literalToOID[literal] = [oid, counter - 1]; + throw("Not matching OID : " + oid + " vs " + oidCounter[0]); } - } else { - throw("Not matching OID : " + oid + " vs " + oidCounter[0]); - } } else if (kind === 'blank') { - delete this.OIDToBlank["" + oid]; + delete this.OIDToBlank["" + oid]; } - }; +}; -// end of ./src/js-rdf-persistence/src/web_local_storage_lexicon.js +// end of ./src/js-rdf-persistence/src/lexicon.js // exports - var NetworkTransport = {}; +var NetworkTransport = {}; - NetworkTransport.load = function (uri, accept, callback, redirect) { +NetworkTransport.load = function (uri, accept, callback, redirect) { var transport = jQuery; transport.ajax({ - url:uri, - headers:{"Accept":accept}, + url:uri, + headers:{"Accept":accept}, - success:function (data, status, xhr) { - if (("" + xhr.status)[0] == '2') { - var headers = xhr.getAllResponseHeaders().split("\n"); - var acum = {}; - for (var i = 0; i < headers.length; i++) { - var header = headers[i].split(":"); - acum[header[0]] = header[1]; - } + success:function (data, status, xhr) { + if (("" + xhr.status)[0] == '2') { + var headers = xhr.getAllResponseHeaders().split("\n"); + var acum = {}; + for (var i = 0; i < headers.length; i++) { + var header = headers[i].split(":"); + acum[header[0]] = header[1]; + } - callback(true, {headers:acum, - data:data}); - } - }, + callback(true, {headers:acum, + data:data}); + } + }, - error:function (xhr, textStatus, ex) { - if (("" + xhr.status)[0] == '3') { - if (redirection == 0) { - callback(false, 500); - } else { - var location = (xhr.getAllResponseHeaders()["Location"] || xhr.getAllResponseHeaders()["location"]); - if (location != null) { - NetworkTransport.load(location, accept, callback, (redirection - 1)); + error:function (xhr, textStatus, ex) { + if (("" + xhr.status)[0] == '3') { + if (redirection == 0) { + callback(false, 500); + } else { + var location = (xhr.getAllResponseHeaders()["Location"] || xhr.getAllResponseHeaders()["location"]); + if (location != null) { + NetworkTransport.load(location, accept, callback, (redirection - 1)); + } else { + callback(false, 500); + } + } } else { - callback(false, 500); + callback(false, xhr.statusCode()); } - } - } else { - callback(false, xhr.statusCode()); } - } }); - }; +}; // end of ./src/js-communication/src/ajax_transport.js - /** - * Javascript implementation of JSON-LD. - * - * @author Dave Longley - * - * Copyright (c) 2011 Digital Bazaar, Inc. All rights reserved. - */ +/** + * Javascript implementation of JSON-LD. + * + * @author Dave Longley + * + * Copyright (c) 2011 Digital Bazaar, Inc. All rights reserved. + */ - var jsonldParser = null; +var jsonldParser = null; - (function() - { +(function() +{ // used by Exception - var _setMembers = function(self, obj) - { - self.stack = ''; - for(var key in obj) - { - self[key] = obj[key]; - } - }; +var _setMembers = function(self, obj) +{ + self.stack = ''; + for(var key in obj) + { + self[key] = obj[key]; + } +}; // define jsonld - if(typeof(window) !== 'undefined') - { - var jsonld = window.jsonld = window.jsonld || {}; - Exception = function(obj) - { - _setMembers(this, obj); - }; +if(typeof(window) !== 'undefined') +{ + var jsonld = window.jsonld = window.jsonld || {}; + Exception = function(obj) + { + _setMembers(this, obj); + }; - // define js 1.8.5 Object.keys method unless present - if(!Object.keys) - { - Object.keys = function(o) - { - if(o !== Object(o)) - { + // define js 1.8.5 Object.keys method unless present + if(!Object.keys) + { + Object.keys = function(o) + { + if(o !== Object(o)) + { throw new TypeError('Object.keys called on non-object'); - } - var rval = []; - for(var p in o) - { + } + var rval = []; + for(var p in o) + { if(Object.prototype.hasOwnProperty.call(o, p)) { - rval.push(p); + rval.push(p); } - } - return rval; - }; - } - - if (!Array.prototype.filter) - { - Array.prototype.filter = function(fun /*, thisp */) - { - "use strict"; - - if (this == null) - throw new TypeError(); - - var t = Object(this); - var len = t.length >>> 0; - if (typeof fun != "function") - throw new TypeError(); - - var res = []; - var thisp = arguments[1]; - for (var i = 0; i < len; i++) - { - if (i in t) - { - var val = t[i]; // in case fun mutates this - if (fun.call(thisp, val, i, t)) - res.push(val); - } - } - - return res; - }; - } - - } -// define node.js module - else if(typeof(module) !== 'undefined' && module.exports) - { - var jsonld = {}; - //module.exports = jsonld; - Exception = function(obj) - { - _setMembers(this, obj); - this.stack = new Error().stack; + } + return rval; }; - } - - - jsonldParser = jsonld; - - var defaultContext = { "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", - "rdfs": "http://www.w3.org/2000/01/rdf-schema#", - "owl": "http://www.w3.org/2002/07/owl#", - "xsd": "http://www.w3.org/2001/XMLSchema#", - "dcterms": "http://purl.org/dc/terms/", - "foaf": "http://xmlns.com/foaf/0.1/", - "cal": "http://www.w3.org/2002/12/cal/ical#", - "vcard": "http://www.w3.org/2006/vcard/ns# ", - "geo": "http://www.w3.org/2003/01/geo/wgs84_pos#", - "cc": "http://creativecommons.org/ns#", - "sioc": "http://rdfs.org/sioc/ns#", - "doap": "http://usefulinc.com/ns/doap#", - "com": "http://purl.org/commerce#", - "ps": "http://purl.org/payswarm#", - "gr": "http://purl.org/goodrelations/v1#", - "sig": "http://purl.org/signature#", - "ccard": "http://purl.org/commerce/creditcard#" - }; - - /* - * Globals and helper functions. - */ - var ns = - { - xsd: 'http://www.w3.org/2001/XMLSchema#' - }; + } - var xsd = - { - 'boolean': ns.xsd + 'boolean', - 'double': ns.xsd + 'double', - 'integer': ns.xsd + 'integer' - }; + if (!Array.prototype.filter) + { + Array.prototype.filter = function(fun /*, thisp */) + { + "use strict"; + + if (this == null) + throw new TypeError(); + + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun != "function") + throw new TypeError(); + + var res = []; + var thisp = arguments[1]; + for (var i = 0; i < len; i++) + { + if (i in t) + { + var val = t[i]; // in case fun mutates this + if (fun.call(thisp, val, i, t)) + res.push(val); + } + } + + return res; + }; + } - /** - * Sets a subject's property to the given object value. If a value already - * exists, it will be appended to an array. - * - * @param s the subject. - * @param p the property. - * @param o the object. - */ - var _setProperty = function(s, p, o) - { - if(p in s) +} +// define node.js module +else if(typeof(module) !== 'undefined' && module.exports) +{ + var jsonld = {}; + //module.exports = jsonld; + Exception = function(obj) + { + _setMembers(this, obj); + this.stack = new Error().stack; + }; +} + + +jsonldParser = jsonld; + +var defaultContext = { "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "owl": "http://www.w3.org/2002/07/owl#", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "dcterms": "http://purl.org/dc/terms/", + "foaf": "http://xmlns.com/foaf/0.1/", + "cal": "http://www.w3.org/2002/12/cal/ical#", + "vcard": "http://www.w3.org/2006/vcard/ns# ", + "geo": "http://www.w3.org/2003/01/geo/wgs84_pos#", + "cc": "http://creativecommons.org/ns#", + "sioc": "http://rdfs.org/sioc/ns#", + "doap": "http://usefulinc.com/ns/doap#", + "com": "http://purl.org/commerce#", + "ps": "http://purl.org/payswarm#", + "gr": "http://purl.org/goodrelations/v1#", + "sig": "http://purl.org/signature#", + "ccard": "http://purl.org/commerce/creditcard#" + }; + +/* + * Globals and helper functions. + */ +var ns = +{ + xsd: 'http://www.w3.org/2001/XMLSchema#' +}; + +var xsd = +{ + 'boolean': ns.xsd + 'boolean', + 'double': ns.xsd + 'double', + 'integer': ns.xsd + 'integer' +}; + +/** + * Sets a subject's property to the given object value. If a value already + * exists, it will be appended to an array. + * + * @param s the subject. + * @param p the property. + * @param o the object. + */ +var _setProperty = function(s, p, o) +{ + if(p in s) + { + if(s[p].constructor === Array) { - if(s[p].constructor === Array) - { - s[p].push(o); - } - else - { - s[p] = [s[p], o]; - } + s[p].push(o); } else { - s[p] = o; + s[p] = [s[p], o]; } - }; - - /** - * Clones an object, array, or string/number. If cloning an object, the keys - * will be sorted. - * - * @param value the value to clone. - * - * @return the cloned value. - */ - var _clone = function(value) - { - var rval; - - if(value.constructor === Object) - { - rval = {}; - var keys = Object.keys(value).sort(); - for(var i in keys) - { - var key = keys[i]; - rval[key] = _clone(value[key]); - } + } + else + { + s[p] = o; + } +}; + +/** + * Clones an object, array, or string/number. If cloning an object, the keys + * will be sorted. + * + * @param value the value to clone. + * + * @return the cloned value. + */ +var _clone = function(value) +{ + var rval; + + if(value.constructor === Object) + { + rval = {}; + var keys = Object.keys(value).sort(); + for(var i in keys) + { + var key = keys[i]; + rval[key] = _clone(value[key]); } - else if(value.constructor === Array) + } + else if(value.constructor === Array) + { + rval = []; + for(var i in value) { - rval = []; - for(var i in value) - { - rval[i] = _clone(value[i]); - } + rval[i] = _clone(value[i]); } - else + } + else + { + rval = value; + } + + return rval; +}; + +/** + * Gets the keywords from a context. + * + * @param ctx the context. + * + * @return the keywords. + */ +var _getKeywords = function(ctx) +{ + // TODO: reduce calls to this function by caching keywords in processor + // state + + var rval = + { + '@id': '@id', + '@language': '@language', + '@literal': '@literal', + '@type': '@type' + }; + + if(ctx) + { + // gather keyword aliases from context + var keywords = {}; + for(var key in ctx) { - rval = value; + if(ctx[key].constructor === String && ctx[key] in rval) + { + keywords[ctx[key]] = key; + } } - - return rval; - }; - - /** - * Gets the keywords from a context. - * - * @param ctx the context. - * - * @return the keywords. - */ - var _getKeywords = function(ctx) - { - // TODO: reduce calls to this function by caching keywords in processor - // state - - var rval = + + // overwrite keywords + for(var key in keywords) { - '@id': '@id', - '@language': '@language', - '@literal': '@literal', - '@type': '@type' - }; - - if(ctx) + rval[key] = keywords[key]; + } + } + + return rval; +}; + +/** + * Gets the iri associated with a term. + * + * @param ctx the context. + * @param term the term. + * + * @return the iri or NULL. + */ +var _getTermIri = function(ctx, term) +{ + var rval = null; + if(term in ctx) + { + if(ctx[term].constructor === String) { - // gather keyword aliases from context - var keywords = {}; - for(var key in ctx) - { - if(ctx[key].constructor === String && ctx[key] in rval) - { - keywords[ctx[key]] = key; - } - } - - // overwrite keywords - for(var key in keywords) - { - rval[key] = keywords[key]; - } + rval = ctx[term]; } - - return rval; - }; - - /** - * Gets the iri associated with a term. - * - * @param ctx the context. - * @param term the term. - * - * @return the iri or NULL. - */ - var _getTermIri = function(ctx, term) - { - var rval = null; - if(term in ctx) + else if(ctx[term].constructor === Object && '@id' in ctx[term]) { - if(ctx[term].constructor === String) - { - rval = ctx[term]; - } - else if(ctx[term].constructor === Object && '@id' in ctx[term]) - { - rval = ctx[term]['@id']; - } + rval = ctx[term]['@id']; } - return rval; - }; - - /** - * Compacts an IRI into a term or prefix if it can be. IRIs will not be - * compacted to relative IRIs if they match the given context's default - * vocabulary. - * - * @param ctx the context to use. - * @param iri the IRI to compact. - * @param usedCtx a context to update if a value was used from "ctx". - * - * @return the compacted IRI as a term or prefix or the original IRI. - */ - var _compactIri = function(ctx, iri, usedCtx) - { - var rval = null; - - // check the context for a term that could shorten the IRI - // (give preference to terms over prefixes) - for(var key in ctx) + } + return rval; +}; + +/** + * Compacts an IRI into a term or prefix if it can be. IRIs will not be + * compacted to relative IRIs if they match the given context's default + * vocabulary. + * + * @param ctx the context to use. + * @param iri the IRI to compact. + * @param usedCtx a context to update if a value was used from "ctx". + * + * @return the compacted IRI as a term or prefix or the original IRI. + */ +var _compactIri = function(ctx, iri, usedCtx) +{ + var rval = null; + + // check the context for a term that could shorten the IRI + // (give preference to terms over prefixes) + for(var key in ctx) + { + // skip special context keys (start with '@') + if(key.length > 0 && key[0] !== '@') { - // skip special context keys (start with '@') - if(key.length > 0 && key[0] !== '@') - { - // compact to a term - if(iri === _getTermIri(ctx, key)) - { + // compact to a term + if(iri === _getTermIri(ctx, key)) + { rval = key; if(usedCtx !== null) { - usedCtx[key] = _clone(ctx[key]); + usedCtx[key] = _clone(ctx[key]); } break; - } - } - } - - // term not found, if term is @type, use keyword - if(rval === null && iri === '@type') - { - rval = _getKeywords(ctx)['@type']; + } } - - // term not found, check the context for a prefix - if(rval === null) + } + + // term not found, if term is @type, use keyword + if(rval === null && iri === '@type') + { + rval = _getKeywords(ctx)['@type']; + } + + // term not found, check the context for a prefix + if(rval === null) + { + for(var key in ctx) { - for(var key in ctx) - { - // skip special context keys (start with '@') - if(key.length > 0 && key[0] !== '@') - { + // skip special context keys (start with '@') + if(key.length > 0 && key[0] !== '@') + { // see if IRI begins with the next IRI from the context var ctxIri = _getTermIri(ctx, key); if(ctxIri !== null) { - var idx = iri.indexOf(ctxIri); - - // compact to a prefix - if(idx === 0 && iri.length > ctxIri.length) - { - rval = key + ':' + iri.substr(ctxIri.length); - if(usedCtx !== null) - { - usedCtx[key] = _clone(ctx[key]); - } - break; - } + var idx = iri.indexOf(ctxIri); + + // compact to a prefix + if(idx === 0 && iri.length > ctxIri.length) + { + rval = key + ':' + iri.substr(ctxIri.length); + if(usedCtx !== null) + { + usedCtx[key] = _clone(ctx[key]); + } + break; + } } - } - } - } - - // could not compact IRI - if(rval === null) - { - rval = iri; + } } + } - return rval; - }; - - /** - * Expands a term into an absolute IRI. The term may be a regular term, a - * prefix, a relative IRI, or an absolute IRI. In any case, the associated - * absolute IRI will be returned. - * - * @param ctx the context to use. - * @param term the term to expand. - * @param usedCtx a context to update if a value was used from "ctx". - * - * @return the expanded term as an absolute IRI. - */ - var _expandTerm = function(ctx, term, usedCtx) - { - var rval = term; - - // get JSON-LD keywords - var keywords = _getKeywords(ctx); + // could not compact IRI + if(rval === null) + { + rval = iri; + } - // 1. If the property has a colon, it is a prefix or an absolute IRI: - var idx = term.indexOf(':'); - if(idx !== -1) + return rval; +}; + +/** + * Expands a term into an absolute IRI. The term may be a regular term, a + * prefix, a relative IRI, or an absolute IRI. In any case, the associated + * absolute IRI will be returned. + * + * @param ctx the context to use. + * @param term the term to expand. + * @param usedCtx a context to update if a value was used from "ctx". + * + * @return the expanded term as an absolute IRI. + */ +var _expandTerm = function(ctx, term, usedCtx) +{ + var rval = term; + + // get JSON-LD keywords + var keywords = _getKeywords(ctx); + + // 1. If the property has a colon, it is a prefix or an absolute IRI: + var idx = term.indexOf(':'); + if(idx !== -1) + { + // get the potential prefix + var prefix = term.substr(0, idx); + + // expand term if prefix is in context, otherwise leave it be + if(prefix in ctx) { - // get the potential prefix - var prefix = term.substr(0, idx); - - // expand term if prefix is in context, otherwise leave it be - if(prefix in ctx) - { - // prefix found, expand property to absolute IRI - var iri = _getTermIri(ctx, prefix); - rval = iri + term.substr(idx + 1); - if(usedCtx !== null) - { + // prefix found, expand property to absolute IRI + var iri = _getTermIri(ctx, prefix); + rval = iri + term.substr(idx + 1); + if(usedCtx !== null) + { usedCtx[prefix] = _clone(ctx[prefix]); - } - } + } } - // 2. If the property is in the context, then it's a term. - else if(term in ctx) + } + // 2. If the property is in the context, then it's a term. + else if(term in ctx) + { + rval = _getTermIri(ctx, term); + if(usedCtx !== null) { - rval = _getTermIri(ctx, term); - if(usedCtx !== null) - { - usedCtx[term] = _clone(ctx[term]); - } + usedCtx[term] = _clone(ctx[term]); } - // 3. The property is a keyword. - else + } + // 3. The property is a keyword. + else + { + for(var key in keywords) { - for(var key in keywords) - { - if(term === keywords[key]) - { + if(term === keywords[key]) + { rval = key; break; - } - } + } } - - return rval; - }; - - /** - * Sorts the keys in a context. - * - * @param ctx the context to sort. - * - * @return the sorted context. - */ - var _sortContextKeys = function(ctx) - { - // sort keys - var rval = {}; - var keys = Object.keys(ctx).sort(); - for(var k in keys) + } + + return rval; +}; + +/** + * Sorts the keys in a context. + * + * @param ctx the context to sort. + * + * @return the sorted context. + */ +var _sortContextKeys = function(ctx) +{ + // sort keys + var rval = {}; + var keys = Object.keys(ctx).sort(); + for(var k in keys) + { + var key = keys[k]; + rval[key] = ctx[key]; + } + return rval; +}; + +/** + * Gets whether or not a value is a reference to a subject (or a subject with + * no properties). + * + * @param value the value to check. + * + * @return true if the value is a reference to a subject, false if not. + */ +var _isReference = function(value) +{ + // Note: A value is a reference to a subject if all of these hold true: + // 1. It is an Object. + // 2. It is has an @id key. + // 3. It has only 1 key. + return (value !== null && + value.constructor === Object && + '@id' in value && + Object.keys(value).length === 1); +}; + +/** + * Gets whether or not a value is a subject with properties. + * + * @param value the value to check. + * + * @return true if the value is a subject with properties, false if not. + */ +var _isSubject = function(value) +{ + var rval = false; + + // Note: A value is a subject if all of these hold true: + // 1. It is an Object. + // 2. It is not a literal. + // 3. It has more than 1 key OR any existing key is not '@id'. + if(value !== null && value.constructor === Object && !('@literal' in value)) + { + var keyCount = Object.keys(value).length; + rval = (keyCount > 1 || !('@id' in value)); + } + + return rval; +}; + +/* + * JSON-LD API. + */ + +/** + * Normalizes a JSON-LD object. + * + * @param input the JSON-LD object to normalize. + * + * @return the normalized JSON-LD object. + */ +jsonld.normalize = function(input) +{ + return new Processor().normalize(input); +}; + +/** + * Removes the context from a JSON-LD object, expanding it to full-form. + * + * @param input the JSON-LD object to remove the context from. + * + * @return the context-neutral JSON-LD object. + */ +jsonld.expand = function(input) +{ + return new Processor().expand({}, null, input); +}; + +/** + * Expands the given JSON-LD object and then compacts it using the + * given context. + * + * @param ctx the new context to use. + * @param input the input JSON-LD object. + * + * @return the output JSON-LD object. + */ +jsonld.compact = function(ctx, input) +{ + var rval = null; + + // TODO: should context simplification be optional? (ie: remove context + // entries that are not used in the output) + + if(input !== null) + { + // fully expand input + input = jsonld.expand(input); + + var tmp; + if(input.constructor === Array) { - var key = keys[k]; - rval[key] = ctx[key]; + rval = []; + tmp = input; } - return rval; - }; - - /** - * Gets whether or not a value is a reference to a subject (or a subject with - * no properties). - * - * @param value the value to check. - * - * @return true if the value is a reference to a subject, false if not. - */ - var _isReference = function(value) - { - // Note: A value is a reference to a subject if all of these hold true: - // 1. It is an Object. - // 2. It is has an @id key. - // 3. It has only 1 key. - return (value !== null && - value.constructor === Object && - '@id' in value && - Object.keys(value).length === 1); - }; - - /** - * Gets whether or not a value is a subject with properties. - * - * @param value the value to check. - * - * @return true if the value is a subject with properties, false if not. - */ - var _isSubject = function(value) - { - var rval = false; - - // Note: A value is a subject if all of these hold true: - // 1. It is an Object. - // 2. It is not a literal. - // 3. It has more than 1 key OR any existing key is not '@id'. - if(value !== null && value.constructor === Object && !('@literal' in value)) + else { - var keyCount = Object.keys(value).length; - rval = (keyCount > 1 || !('@id' in value)); + tmp = [input]; } - - return rval; - }; - - /* - * JSON-LD API. - */ - - /** - * Normalizes a JSON-LD object. - * - * @param input the JSON-LD object to normalize. - * - * @return the normalized JSON-LD object. - */ - jsonld.normalize = function(input) - { - return new Processor().normalize(input); - }; - - /** - * Removes the context from a JSON-LD object, expanding it to full-form. - * - * @param input the JSON-LD object to remove the context from. - * - * @return the context-neutral JSON-LD object. - */ - jsonld.expand = function(input) - { - return new Processor().expand({}, null, input); - }; - - /** - * Expands the given JSON-LD object and then compacts it using the - * given context. - * - * @param ctx the new context to use. - * @param input the input JSON-LD object. - * - * @return the output JSON-LD object. - */ - jsonld.compact = function(ctx, input) - { - var rval = null; - - // TODO: should context simplification be optional? (ie: remove context - // entries that are not used in the output) - - if(input !== null) + + // merge context if it is an array + if(ctx.constructor === Array) { - // fully expand input - input = jsonld.expand(input); - - var tmp; - if(input.constructor === Array) - { - rval = []; - tmp = input; - } - else - { - tmp = [input]; - } - - // merge context if it is an array - if(ctx.constructor === Array) - { - ctx = jsonld.mergeContexts({}, ctx); - } - - for(var i in tmp) - { - // setup output context - var ctxOut = {}; - - // compact - var out = new Processor().compact(_clone(ctx), null, tmp[i], ctxOut); - - // add context if used - if(Object.keys(ctxOut).length > 0) - { + ctx = jsonld.mergeContexts({}, ctx); + } + + for(var i in tmp) + { + // setup output context + var ctxOut = {}; + + // compact + var out = new Processor().compact(_clone(ctx), null, tmp[i], ctxOut); + + // add context if used + if(Object.keys(ctxOut).length > 0) + { // sort context keys ctxOut = _sortContextKeys(ctxOut); - + // sort keys var keys = Object.keys(out); keys.sort(); - + // put @context first keys.unshift('@context'); out['@context'] = ctxOut; - + // order keys in output var ordered = {}; for(var k in keys) { - var key = keys[k]; - ordered[key] = out[key]; + var key = keys[k]; + ordered[key] = out[key]; } out = ordered; - } - - if(rval === null) - { + } + + if(rval === null) + { rval = out; - } - else - { + } + else + { rval.push(out); - } - } - } - - return rval; - }; - - /** - * Merges one context with another. - * - * @param ctx1 the context to overwrite/append to. - * @param ctx2 the new context to merge onto ctx1. - * - * @return the merged context. - */ - jsonld.mergeContexts = function(ctx1, ctx2) - { - // merge first context if it is an array - if(ctx1.constructor === Array) - { - ctx1 = jsonld.mergeContexts({}, ctx1); + } } + } - // copy context to merged output - var merged = _clone(ctx1); - - if(ctx2.constructor === Array) + return rval; +}; + +/** + * Merges one context with another. + * + * @param ctx1 the context to overwrite/append to. + * @param ctx2 the new context to merge onto ctx1. + * + * @return the merged context. + */ +jsonld.mergeContexts = function(ctx1, ctx2) +{ + // merge first context if it is an array + if(ctx1.constructor === Array) + { + ctx1 = jsonld.mergeContexts({}, ctx1); + } + + // copy context to merged output + var merged = _clone(ctx1); + + if(ctx2.constructor === Array) + { + // merge array of contexts in order + for(var i in ctx2) { - // merge array of contexts in order - for(var i in ctx2) - { - merged = jsonld.mergeContexts(merged, ctx2[i]); - } + merged = jsonld.mergeContexts(merged, ctx2[i]); } - else + } + else + { + // if the new context contains any IRIs that are in the merged context, + // remove them from the merged context, they will be overwritten + for(var key in ctx2) { - // if the new context contains any IRIs that are in the merged context, - // remove them from the merged context, they will be overwritten - for(var key in ctx2) - { - // ignore special keys starting with '@' - if(key.indexOf('@') !== 0) - { + // ignore special keys starting with '@' + if(key.indexOf('@') !== 0) + { for(var mkey in merged) { - if(merged[mkey] === ctx2[key]) - { - // FIXME: update related coerce rules - delete merged[mkey]; - break; - } + if(merged[mkey] === ctx2[key]) + { + // FIXME: update related coerce rules + delete merged[mkey]; + break; + } } - } - } - - // merge contexts - for(var key in ctx2) - { - merged[key] = _clone(ctx2[key]); - } + } } - - return merged; - }; - - /** - * Expands a term into an absolute IRI. The term may be a regular term, a - * prefix, a relative IRI, or an absolute IRI. In any case, the associated - * absolute IRI will be returned. - * - * @param ctx the context to use. - * @param term the term to expand. - * - * @return the expanded term as an absolute IRI. - */ - jsonld.expandTerm = _expandTerm; - - /** - * Compacts an IRI into a term or prefix if it can be. IRIs will not be - * compacted to relative IRIs if they match the given context's default - * vocabulary. - * - * @param ctx the context to use. - * @param iri the IRI to compact. - * - * @return the compacted IRI as a term or prefix or the original IRI. - */ - jsonld.compactIri = function(ctx, iri) - { - return _compactIri(ctx, iri, null); - }; - - /** - * Frames JSON-LD input. - * - * @param input the JSON-LD input. - * @param frame the frame to use. - * @param options framing options to use. - * - * @return the framed output. - */ - jsonld.frame = function(input, frame, options) - { - return new Processor().frame(input, frame, options); - }; - - /** - * Generates triples given a JSON-LD input. Each triple that is generated - * results in a call to the given callback. The callback takes 3 parameters: - * subject, property, and object. If the callback returns false then this - * method will stop generating triples and return. If the callback is null, - * then an array with triple objects containing "s", "p", "o" properties will - * be returned. - * - * The object or "o" property will be a JSON-LD formatted object. - * - * @param input the JSON-LD input. - * @param callback the triple callback. - * - * @return an array of triple objects if callback is null, null otherwise. - */ - jsonld.toTriples = function(input, graph, callback) - { - var rval = null; - - // normalize input - var normalized = jsonld.normalize(input); - - // setup default callback - callback = callback || null; - if(callback === null) + + // merge contexts + for(var key in ctx2) { - rval = []; - callback = function(s, p, o) - { - rval.push({'subject': Utils.lexicalFormTerm(s), - 'predicate': Utils.lexicalFormTerm(p), - 'object': Utils.lexicalFormTerm(o), - 'graph': graph}); - }; + merged[key] = _clone(ctx2[key]); } + } - // generate triples - var quit = false; - for(var i1 in normalized) + return merged; +}; + +/** + * Expands a term into an absolute IRI. The term may be a regular term, a + * prefix, a relative IRI, or an absolute IRI. In any case, the associated + * absolute IRI will be returned. + * + * @param ctx the context to use. + * @param term the term to expand. + * + * @return the expanded term as an absolute IRI. + */ +jsonld.expandTerm = _expandTerm; + +/** + * Compacts an IRI into a term or prefix if it can be. IRIs will not be + * compacted to relative IRIs if they match the given context's default + * vocabulary. + * + * @param ctx the context to use. + * @param iri the IRI to compact. + * + * @return the compacted IRI as a term or prefix or the original IRI. + */ +jsonld.compactIri = function(ctx, iri) +{ + return _compactIri(ctx, iri, null); +}; + +/** + * Frames JSON-LD input. + * + * @param input the JSON-LD input. + * @param frame the frame to use. + * @param options framing options to use. + * + * @return the framed output. + */ +jsonld.frame = function(input, frame, options) +{ + return new Processor().frame(input, frame, options); +}; + +/** + * Generates triples given a JSON-LD input. Each triple that is generated + * results in a call to the given callback. The callback takes 3 parameters: + * subject, property, and object. If the callback returns false then this + * method will stop generating triples and return. If the callback is null, + * then an array with triple objects containing "s", "p", "o" properties will + * be returned. + * + * The object or "o" property will be a JSON-LD formatted object. + * + * @param input the JSON-LD input. + * @param callback the triple callback. + * + * @return an array of triple objects if callback is null, null otherwise. + */ +jsonld.toTriples = function(input, graph, callback) +{ + var rval = null; + + // normalize input + var normalized = jsonld.normalize(input); + + // setup default callback + callback = callback || null; + if(callback === null) + { + rval = []; + callback = function(s, p, o) { - var e = normalized[i1]; - var s = e['@id']; - if(s[0] == "_") { - s = {'token':'blank', 'value':s.split(":")[1]}; - } else { - s = {'token':'uri', 'value':s}; - } - - for(var p in e) - { - if(p !== '@id') - { - var obj = e[p]; - if(obj.constructor !== Array) - { - obj = [obj]; - } + rval.push({'subject': Utils.lexicalFormTerm(s), + 'predicate': Utils.lexicalFormTerm(p), + 'object': Utils.lexicalFormTerm(o), + 'graph': graph}); + }; + } + + // generate triples + var quit = false; + for(var i1 in normalized) + { + var e = normalized[i1]; + var s = e['@id']; + if(s[0] == "_") { + s = {'token':'blank', 'value':s.split(":")[1]}; + } else { + s = {'token':'uri', 'value':s}; + } + + for(var p in e) + { + if(p !== '@id') + { + var obj = e[p]; + if(obj.constructor !== Array) + { + obj = [obj]; + } for(var i2 in obj) { - var obji2 = obj[i2]; - if(p === '@type' || p === 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') { - p = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'; - obji2 = {'token':'uri', 'value':obji2}; - } else if(typeof(obji2) === 'string') { - obji2 = {'token': 'literal', 'value':obji2}; - } else if(obji2['@id'] != null) { - if(obji2['@id'][0] == "_") { - obji2 = {'token':'blank', 'value':obji2['@id'].split(":")[1]}; - } else { - obji2 = {'token':'uri', 'value':obji2['@id']}; + var obji2 = obj[i2]; + if(p === '@type' || p === 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') { + p = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'; + obji2 = {'token':'uri', 'value':obji2}; + } else if(typeof(obji2) === 'string') { + obji2 = {'token': 'literal', 'value':obji2}; + } else if(obji2['@id'] != null) { + if(obji2['@id'][0] == "_") { + obji2 = {'token':'blank', 'value':obji2['@id'].split(":")[1]}; + } else { + obji2 = {'token':'uri', 'value':obji2['@id']}; + } + } else if(obji2['@type'] != null) { + obji2 = {'token':'literal', 'value':obji2['@literal'], 'type':obji2['@type']}; + } else if(obji2['@language'] != null) { + obji2 = {'token':'literal', 'value':obji2['@literal'], 'lang':obji2['@language']}; } - } else if(obji2['@type'] != null) { - obji2 = {'token':'literal', 'value':obji2['@literal'], 'type':obji2['@type']}; - } else if(obji2['@language'] != null) { - obji2 = {'token':'literal', 'value':obji2['@literal'], 'lang':obji2['@language']}; - } - quit = (callback(s, {'token':'uri', 'value':p}, obji2) === false); - if(quit) - { - break; - } + quit = (callback(s, {'token':'uri', 'value':p}, obji2) === false); + if(quit) + { + break; + } } if(quit) { - break; + break; } - } - } - if(quit) - { - break; - } + } } - - return rval; - }; - - /** - * Resolves external @context URLs. Every @context URL in the given JSON-LD - * object is resolved using the given URL-resolver function. Once all of - * the @contexts have been resolved, the given result callback is invoked. - * - * @param input the JSON-LD input object (or array). - * @param resolver the resolver method that takes a URL and a callback that - * receives a JSON-LD serialized @context or null on error (with - * optional an error object as the second parameter). - * @param callback the callback to be invoked with the fully-resolved - * JSON-LD output (object or array) or null on error (with an - * optional error array as the second parameter). - */ - jsonld.resolve = function(input, resolver, callback) - { - // find all @context URLs - var urls = {}; - var findUrls = function(input, replace) + if(quit) { - if(input.constructor === Array) - { - for(var i in input) - { - findUrls(input[i]); - } - } - else if(input.constructor === Object) - { - for(var key in input) - { + break; + } + } + + return rval; +}; + +/** + * Resolves external @context URLs. Every @context URL in the given JSON-LD + * object is resolved using the given URL-resolver function. Once all of + * the @contexts have been resolved, the given result callback is invoked. + * + * @param input the JSON-LD input object (or array). + * @param resolver the resolver method that takes a URL and a callback that + * receives a JSON-LD serialized @context or null on error (with + * optional an error object as the second parameter). + * @param callback the callback to be invoked with the fully-resolved + * JSON-LD output (object or array) or null on error (with an + * optional error array as the second parameter). + */ +jsonld.resolve = function(input, resolver, callback) +{ + // find all @context URLs + var urls = {}; + var findUrls = function(input, replace) + { + if(input.constructor === Array) + { + for(var i in input) + { + findUrls(input[i]); + } + } + else if(input.constructor === Object) + { + for(var key in input) + { if(key === '@context') { - // @context is an array that might contain URLs - if(input[key].constructor === Array) - { - var list = input[key]; - for(var i in list) - { - if(list[i].constructor === String) + // @context is an array that might contain URLs + if(input[key].constructor === Array) + { + var list = input[key]; + for(var i in list) { - // replace w/resolved @context if appropriate - if(replace) - { - list[i] = urls[list[i]]; - } - // unresolved @context found - else - { - urls[list[i]] = {}; - } + if(list[i].constructor === String) + { + // replace w/resolved @context if appropriate + if(replace) + { + list[i] = urls[list[i]]; + } + // unresolved @context found + else + { + urls[list[i]] = {}; + } + } } - } - } - else if(input[key].constructor === String) - { - // replace w/resolved @context if appropriate - if(replace) - { - input[key] = urls[input[key]]; - } - // unresolved @context found - else - { - urls[input[key]] = {}; - } - } + } + else if(input[key].constructor === String) + { + // replace w/resolved @context if appropriate + if(replace) + { + input[key] = urls[input[key]]; + } + // unresolved @context found + else + { + urls[input[key]] = {}; + } + } } - } - } - }; - findUrls(input, false); - - // state for resolving URLs - var count = Object.keys(urls).length; - var errors = null; - - if(count === 0) - { - callback(input, errors); + } } - else + }; + findUrls(input, false); + + // state for resolving URLs + var count = Object.keys(urls).length; + var errors = null; + + if(count === 0) + { + callback(input, errors); + } + else + { + // resolve all URLs + for(var url in urls) { - // resolve all URLs - for(var url in urls) - { - resolver(url, function(result, error) - { + resolver(url, function(result, error) + { --count; - + if(result === null) { - errors = errors || []; - errors.push({ url: url, error: error }); + errors = errors || []; + errors.push({ url: url, error: error }); } else { - try - { - if(result.constructor === String) - { - urls[url] = JSON.parse(result)['@context']; - } - else - { - urls[url] = result['@context']; - } - } - catch(ex) - { - errors = errors || []; - errors.push({ url: url, error: ex }); - } + try + { + if(result.constructor === String) + { + urls[url] = JSON.parse(result)['@context']; + } + else + { + urls[url] = result['@context']; + } + } + catch(ex) + { + errors = errors || []; + errors.push({ url: url, error: ex }); + } } - + if(count === 0) { - if(errors === null) - { - findUrls(input, true); - } - callback(input, errors); + if(errors === null) + { + findUrls(input, true); + } + callback(input, errors); } - }); - } + }); } - }; + } +}; // TODO: organizational rewrite - /** - * Constructs a new JSON-LD processor. - */ - var Processor = function() - { - }; - - /** - * Recursively compacts a value. This method will compact IRIs to prefixes or - * terms and do reverse type coercion to compact a value. - * - * @param ctx the context to use. - * @param property the property that points to the value, NULL for none. - * @param value the value to compact. - * @param usedCtx a context to update if a value was used from "ctx". - * - * @return the compacted value. - */ - Processor.prototype.compact = function(ctx, property, value, usedCtx) - { - var rval; - - // get JSON-LD keywords - var keywords = _getKeywords(ctx); - - if(value === null) - { - // return null, but check coerce type to add to usedCtx - rval = null; - this.getCoerceType(ctx, property, usedCtx); - } - else if(value.constructor === Array) - { - // recursively add compacted values to array - rval = []; - for(var i in value) - { - rval.push(this.compact(ctx, property, value[i], usedCtx)); - } - } - // graph literal/disjoint graph - else if( - value.constructor === Object && - '@id' in value && value['@id'].constructor === Array) +/** + * Constructs a new JSON-LD processor. + */ +var Processor = function() +{ +}; + +/** + * Recursively compacts a value. This method will compact IRIs to prefixes or + * terms and do reverse type coercion to compact a value. + * + * @param ctx the context to use. + * @param property the property that points to the value, NULL for none. + * @param value the value to compact. + * @param usedCtx a context to update if a value was used from "ctx". + * + * @return the compacted value. + */ +Processor.prototype.compact = function(ctx, property, value, usedCtx) +{ + var rval; + + // get JSON-LD keywords + var keywords = _getKeywords(ctx); + + if(value === null) + { + // return null, but check coerce type to add to usedCtx + rval = null; + this.getCoerceType(ctx, property, usedCtx); + } + else if(value.constructor === Array) + { + // recursively add compacted values to array + rval = []; + for(var i in value) { - rval = {}; - rval[keywords['@id']] = this.compact( - ctx, property, value['@id'], usedCtx); + rval.push(this.compact(ctx, property, value[i], usedCtx)); } - // recurse if value is a subject - else if(_isSubject(value)) + } + // graph literal/disjoint graph + else if( + value.constructor === Object && + '@id' in value && value['@id'].constructor === Array) + { + rval = {}; + rval[keywords['@id']] = this.compact( + ctx, property, value['@id'], usedCtx); + } + // recurse if value is a subject + else if(_isSubject(value)) + { + // recursively handle sub-properties that aren't a sub-context + rval = {}; + for(var key in value) { - // recursively handle sub-properties that aren't a sub-context - rval = {}; - for(var key in value) - { - if(value[key] !== '@context') - { + if(value[key] !== '@context') + { // set object to compacted property, only overwrite existing // properties if the property actually compacted var p = _compactIri(ctx, key, usedCtx); if(p !== key || !(p in rval)) { - // FIXME: clean old values from the usedCtx here ... or just - // change usedCtx to be built at the end of processing? - rval[p] = this.compact(ctx, key, value[key], usedCtx); + // FIXME: clean old values from the usedCtx here ... or just + // change usedCtx to be built at the end of processing? + rval[p] = this.compact(ctx, key, value[key], usedCtx); } - } - } + } } - else + } + else + { + // get coerce type + var coerce = this.getCoerceType(ctx, property, usedCtx); + + // get type from value, to ensure coercion is valid + var type = null; + if(value.constructor === Object) { - // get coerce type - var coerce = this.getCoerceType(ctx, property, usedCtx); - - // get type from value, to ensure coercion is valid - var type = null; - if(value.constructor === Object) - { - // type coercion can only occur if language is not specified - if(!('@language' in value)) - { + // type coercion can only occur if language is not specified + if(!('@language' in value)) + { // type must match coerce type if specified if('@type' in value) { - type = value['@type']; + type = value['@type']; } // type is ID (IRI) else if('@id' in value) { - type = '@id'; + type = '@id'; } // can be coerced to any type else { - type = coerce; + type = coerce; } - } - } - // type can be coerced to anything - else if(value.constructor === String) - { - type = coerce; - } + } + } + // type can be coerced to anything + else if(value.constructor === String) + { + type = coerce; + } - // types that can be auto-coerced from a JSON-builtin - if(coerce === null && - (type === xsd['boolean'] || type === xsd['integer'] || - type === xsd['double'])) - { - coerce = type; - } + // types that can be auto-coerced from a JSON-builtin + if(coerce === null && + (type === xsd['boolean'] || type === xsd['integer'] || + type === xsd['double'])) + { + coerce = type; + } - // do reverse type-coercion - if(coerce !== null) - { - // type is only null if a language was specified, which is an error - // if type coercion is specified - if(type === null) - { + // do reverse type-coercion + if(coerce !== null) + { + // type is only null if a language was specified, which is an error + // if type coercion is specified + if(type === null) + { throw { - message: 'Cannot coerce type when a language is specified. ' + - 'The language information would be lost.' + message: 'Cannot coerce type when a language is specified. ' + + 'The language information would be lost.' }; - } - // if the value type does not match the coerce type, it is an error - else if(type !== coerce) - { + } + // if the value type does not match the coerce type, it is an error + else if(type !== coerce) + { throw new Exception({ - message: 'Cannot coerce type because the type does ' + - 'not match.', - type: type, - expected: coerce + message: 'Cannot coerce type because the type does ' + + 'not match.', + type: type, + expected: coerce }); - } - // do reverse type-coercion - else - { + } + // do reverse type-coercion + else + { if(value.constructor === Object) { - if('@id' in value) - { - rval = value['@id']; - } - else if('@literal' in value) - { - rval = value['@literal']; - } + if('@id' in value) + { + rval = value['@id']; + } + else if('@literal' in value) + { + rval = value['@literal']; + } } else { - rval = value; + rval = value; } // do basic JSON types conversion if(coerce === xsd['boolean']) { - rval = (rval === 'true' || rval != 0); + rval = (rval === 'true' || rval != 0); } else if(coerce === xsd['double']) { - rval = parseFloat(rval); + rval = parseFloat(rval); } else if(coerce === xsd['integer']) { - rval = parseInt(rval); + rval = parseInt(rval); } - } - } - // no type-coercion, just change keywords/copy value - else if(value.constructor === Object) - { - rval = {}; - for(var key in value) - { + } + } + // no type-coercion, just change keywords/copy value + else if(value.constructor === Object) + { + rval = {}; + for(var key in value) + { rval[keywords[key]] = value[key]; - } - } - else - { - rval = _clone(value); - } + } + } + else + { + rval = _clone(value); + } - // compact IRI - if(type === '@id') - { - if(rval.constructor === Object) - { + // compact IRI + if(type === '@id') + { + if(rval.constructor === Object) + { rval[keywords['@id']] = _compactIri( - ctx, rval[keywords['@id']], usedCtx); - } - else - { + ctx, rval[keywords['@id']], usedCtx); + } + else + { rval = _compactIri(ctx, rval, usedCtx); - } - } + } } + } - return rval; - }; - - /** - * Recursively expands a value using the given context. Any context in - * the value will be removed. - * - * @param ctx the context. - * @param property the property that points to the value, NULL for none. - * @param value the value to expand. - * - * @return the expanded value. - */ - Processor.prototype.expand = function(ctx, property, value) - { - var rval; - - // TODO: add data format error detection? - - // value is null, nothing to expand - if(value === null) - { - rval = null; - } - // if no property is specified and the value is a string (this means the - // value is a property itself), expand to an IRI - else if(property === null && value.constructor === String) + return rval; +}; + +/** + * Recursively expands a value using the given context. Any context in + * the value will be removed. + * + * @param ctx the context. + * @param property the property that points to the value, NULL for none. + * @param value the value to expand. + * + * @return the expanded value. + */ +Processor.prototype.expand = function(ctx, property, value) +{ + var rval; + + // TODO: add data format error detection? + + // value is null, nothing to expand + if(value === null) + { + rval = null; + } + // if no property is specified and the value is a string (this means the + // value is a property itself), expand to an IRI + else if(property === null && value.constructor === String) + { + rval = _expandTerm(ctx, value, null); + } + else if(value.constructor === Array) + { + // recursively add expanded values to array + rval = []; + for(var i in value) { - rval = _expandTerm(ctx, value, null); + rval.push(this.expand(ctx, property, value[i])); } - else if(value.constructor === Array) + } + else if(value.constructor === Object) + { + // if value has a context, use it + if('@context' in value) { - // recursively add expanded values to array - rval = []; - for(var i in value) - { - rval.push(this.expand(ctx, property, value[i])); - } + ctx = jsonld.mergeContexts(ctx, value['@context']); } - else if(value.constructor === Object) + + // recursively handle sub-properties that aren't a sub-context + rval = {}; + for(var key in value) { - // if value has a context, use it - if('@context' in value) - { - ctx = jsonld.mergeContexts(ctx, value['@context']); - } - - // recursively handle sub-properties that aren't a sub-context - rval = {}; - for(var key in value) - { - // preserve frame keywords - if(key === '@embed' || key === '@explicit' || + // preserve frame keywords + if(key === '@embed' || key === '@explicit' || key === '@default' || key === '@omitDefault') - { + { _setProperty(rval, key, _clone(value[key])); - } - else if(key !== '@context') - { + } + else if(key !== '@context') + { // set object to expanded property _setProperty( - rval, _expandTerm(ctx, key, null), - this.expand(ctx, key, value[key])); - } - } + rval, _expandTerm(ctx, key, null), + this.expand(ctx, key, value[key])); + } } - else + } + else + { + // do type coercion + var coerce = this.getCoerceType(ctx, property, null); + + // get JSON-LD keywords + var keywords = _getKeywords(ctx); + + // automatic coercion for basic JSON types + if(coerce === null && + (value.constructor === Number || value.constructor === Boolean)) { - // do type coercion - var coerce = this.getCoerceType(ctx, property, null); - - // get JSON-LD keywords - var keywords = _getKeywords(ctx); - - // automatic coercion for basic JSON types - if(coerce === null && - (value.constructor === Number || value.constructor === Boolean)) - { - if(value.constructor === Boolean) - { + if(value.constructor === Boolean) + { coerce = xsd['boolean']; - } - else if(('' + value).indexOf('.') == -1) - { + } + else if(('' + value).indexOf('.') == -1) + { coerce = xsd['integer']; - } - else - { + } + else + { coerce = xsd['double']; - } - } - - // special-case expand @id and @type (skips '@id' expansion) - if(property === keywords['@id'] || property === keywords['@type']) - { - rval = _expandTerm(ctx, value, null); - } - // coerce to appropriate type - else if(coerce !== null) - { - rval = {}; - - // expand ID (IRI) - if(coerce === '@id') - { + } + } + + // special-case expand @id and @type (skips '@id' expansion) + if(property === keywords['@id'] || property === keywords['@type']) + { + rval = _expandTerm(ctx, value, null); + } + // coerce to appropriate type + else if(coerce !== null) + { + rval = {}; + + // expand ID (IRI) + if(coerce === '@id') + { rval['@id'] = _expandTerm(ctx, value, null); - } - // other type - else - { + } + // other type + else + { rval['@type'] = coerce; if(coerce === xsd['double']) { - // do special JSON-LD double format - value = value.toExponential(6).replace( - /(e(?:\+|-))([0-9])$/, '$10$2'); + // do special JSON-LD double format + value = value.toExponential(6).replace( + /(e(?:\+|-))([0-9])$/, '$10$2'); } rval['@literal'] = '' + value; - } - } - // nothing to coerce - else - { - rval = '' + value; - } + } } - - return rval; - }; - - /** - * Normalizes a JSON-LD object. - * - * @param input the JSON-LD object to normalize. - * - * @return the normalized JSON-LD object. - */ - Processor.prototype.normalize = function(input) - { - var rval = []; - - // TODO: validate context - - if(input !== null) + // nothing to coerce + else { - // create name generator state - this.ng = - { - tmp: null, - c14n: null - }; - - // expand input - var expanded = this.expand(defaultContext, null, input); - - // assign names to unnamed bnodes - this.nameBlankNodes(expanded); - - // flatten - var subjects = {}; - _flatten(null, null, expanded, subjects); + rval = '' + value; + } + } + + return rval; +}; + +/** + * Normalizes a JSON-LD object. + * + * @param input the JSON-LD object to normalize. + * + * @return the normalized JSON-LD object. + */ +Processor.prototype.normalize = function(input) +{ + var rval = []; + + // TODO: validate context + + if(input !== null) + { + // create name generator state + this.ng = + { + tmp: null, + c14n: null + }; + + // expand input + var expanded = this.expand(defaultContext, null, input); + + // assign names to unnamed bnodes + this.nameBlankNodes(expanded); + + // flatten + var subjects = {}; + _flatten(null, null, expanded, subjects); - // append subjects with sorted properties to array - for(var key in subjects) - { - var s = subjects[key]; - var sorted = {}; - var keys = Object.keys(s).sort(); - for(var i in keys) - { + // append subjects with sorted properties to array + for(var key in subjects) + { + var s = subjects[key]; + var sorted = {}; + var keys = Object.keys(s).sort(); + for(var i in keys) + { var k = keys[i]; sorted[k] = s[k]; - } - rval.push(sorted); - } - - // canonicalize blank nodes - this.canonicalizeBlankNodes(rval); - - // sort output - rval.sort(function(a, b) - { - return _compare(a['@id'], b['@id']); - }); + } + rval.push(sorted); } - return rval; - }; - - /** - * Gets the coerce type for the given property. - * - * @param ctx the context to use. - * @param property the property to get the coerced type for. - * @param usedCtx a context to update if a value was used from "ctx". - * - * @return the coerce type, null for none. - */ - Processor.prototype.getCoerceType = function(ctx, property, usedCtx) - { - var rval = null; + // canonicalize blank nodes + this.canonicalizeBlankNodes(rval); - // get expanded property - var p = _expandTerm(ctx, property, null); + // sort output + rval.sort(function(a, b) + { + return _compare(a['@id'], b['@id']); + }); + } - // built-in type coercion JSON-LD-isms - if(p === '@id' || p === '@type') + return rval; +}; + +/** + * Gets the coerce type for the given property. + * + * @param ctx the context to use. + * @param property the property to get the coerced type for. + * @param usedCtx a context to update if a value was used from "ctx". + * + * @return the coerce type, null for none. + */ +Processor.prototype.getCoerceType = function(ctx, property, usedCtx) +{ + var rval = null; + + // get expanded property + var p = _expandTerm(ctx, property, null); + + // built-in type coercion JSON-LD-isms + if(p === '@id' || p === '@type') + { + rval = '@id'; + } + else + { + // look up compacted property for a coercion type + p = _compactIri(ctx, p, null); + if(p in ctx && ctx[p].constructor === Object && '@type' in ctx[p]) { - rval = '@id'; + // property found, return expanded type + var type = ctx[p]['@type']; + rval = _expandTerm(ctx, type, usedCtx); + if(usedCtx !== null) + { + usedCtx[p] = _clone(ctx[p]); + } } - else + } + + return rval; +}; + +var _isBlankNodeIri = function(v) +{ + return v.indexOf('_:') === 0; +}; + +var _isNamedBlankNode = function(v) +{ + // look for "_:" at the beginning of the subject + return ( + v.constructor === Object && '@id' in v && _isBlankNodeIri(v['@id'])); +}; + +var _isBlankNode = function(v) +{ + // look for a subject with no ID or a blank node ID + return (_isSubject(v) && (!('@id' in v) || _isNamedBlankNode(v))); +}; + +/** + * Compares two values. + * + * @param v1 the first value. + * @param v2 the second value. + * + * @return -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2. + */ +var _compare = function(v1, v2) +{ + var rval = 0; + + if(v1.constructor === Array && v2.constructor === Array) + { + for(var i = 0; i < v1.length && rval === 0; ++i) { - // look up compacted property for a coercion type - p = _compactIri(ctx, p, null); - if(p in ctx && ctx[p].constructor === Object && '@type' in ctx[p]) - { - // property found, return expanded type - var type = ctx[p]['@type']; - rval = _expandTerm(ctx, type, usedCtx); - if(usedCtx !== null) - { - usedCtx[p] = _clone(ctx[p]); - } - } + rval = _compare(v1[i], v2[i]); } - - return rval; - }; - - var _isBlankNodeIri = function(v) - { - return v.indexOf('_:') === 0; - }; - - var _isNamedBlankNode = function(v) - { - // look for "_:" at the beginning of the subject - return ( - v.constructor === Object && '@id' in v && _isBlankNodeIri(v['@id'])); - }; - - var _isBlankNode = function(v) - { - // look for a subject with no ID or a blank node ID - return (_isSubject(v) && (!('@id' in v) || _isNamedBlankNode(v))); - }; - - /** - * Compares two values. - * - * @param v1 the first value. - * @param v2 the second value. - * - * @return -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2. - */ - var _compare = function(v1, v2) - { - var rval = 0; - - if(v1.constructor === Array && v2.constructor === Array) + } + else + { + rval = (v1 < v2 ? -1 : (v1 > v2 ? 1 : 0)); + } + + return rval; +}; + +/** + * Compares two keys in an object. If the key exists in one object + * and not the other, the object with the key is less. If the key exists in + * both objects, then the one with the lesser value is less. + * + * @param o1 the first object. + * @param o2 the second object. + * @param key the key. + * + * @return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2. + */ +var _compareObjectKeys = function(o1, o2, key) +{ + var rval = 0; + if(key in o1) + { + if(key in o2) { - for(var i = 0; i < v1.length && rval === 0; ++i) - { - rval = _compare(v1[i], v2[i]); - } + rval = _compare(o1[key], o2[key]); } else { - rval = (v1 < v2 ? -1 : (v1 > v2 ? 1 : 0)); + rval = -1; } - - return rval; - }; - - /** - * Compares two keys in an object. If the key exists in one object - * and not the other, the object with the key is less. If the key exists in - * both objects, then the one with the lesser value is less. - * - * @param o1 the first object. - * @param o2 the second object. - * @param key the key. - * - * @return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2. - */ - var _compareObjectKeys = function(o1, o2, key) - { - var rval = 0; - if(key in o1) - { - if(key in o2) - { - rval = _compare(o1[key], o2[key]); - } - else - { - rval = -1; - } - } - else if(key in o2) - { - rval = 1; - } - return rval; - }; - - /** - * Compares two object values. - * - * @param o1 the first object. - * @param o2 the second object. - * - * @return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2. - */ - var _compareObjects = function(o1, o2) - { - var rval = 0; - - if(o1.constructor === String) + } + else if(key in o2) + { + rval = 1; + } + return rval; +}; + +/** + * Compares two object values. + * + * @param o1 the first object. + * @param o2 the second object. + * + * @return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2. + */ +var _compareObjects = function(o1, o2) +{ + var rval = 0; + + if(o1.constructor === String) + { + if(o2.constructor !== String) { - if(o2.constructor !== String) - { - rval = -1; - } - else - { - rval = _compare(o1, o2); - } + rval = -1; } - else if(o2.constructor === String) + else { - rval = 1; + rval = _compare(o1, o2); } - else + } + else if(o2.constructor === String) + { + rval = 1; + } + else + { + rval = _compareObjectKeys(o1, o2, '@literal'); + if(rval === 0) { - rval = _compareObjectKeys(o1, o2, '@literal'); - if(rval === 0) - { - if('@literal' in o1) - { + if('@literal' in o1) + { rval = _compareObjectKeys(o1, o2, '@type'); if(rval === 0) { - rval = _compareObjectKeys(o1, o2, '@language'); + rval = _compareObjectKeys(o1, o2, '@language'); } - } - // both are '@id' objects - else - { + } + // both are '@id' objects + else + { rval = _compare(o1['@id'], o2['@id']); - } - } + } } - - return rval; - }; - - /** - * Compares the object values between two bnodes. - * - * @param a the first bnode. - * @param b the second bnode. - * - * @return -1 if a < b, 0 if a == b, 1 if a > b. - */ - var _compareBlankNodeObjects = function(a, b) - { - var rval = 0; - - /* - 3. For each property, compare sorted object values. - 3.1. The bnode with fewer objects is first. - 3.2. For each object value, compare only literals and non-bnodes. - 3.2.1. The bnode with fewer non-bnodes is first. - 3.2.2. The bnode with a string object is first. - 3.2.3. The bnode with the alphabetically-first string is first. - 3.2.4. The bnode with a @literal is first. - 3.2.5. The bnode with the alphabetically-first @literal is first. - 3.2.6. The bnode with the alphabetically-first @type is first. - 3.2.7. The bnode with a @language is first. - 3.2.8. The bnode with the alphabetically-first @language is first. - 3.2.9. The bnode with the alphabetically-first @id is first. - */ - - for(var p in a) + } + + return rval; +}; + +/** + * Compares the object values between two bnodes. + * + * @param a the first bnode. + * @param b the second bnode. + * + * @return -1 if a < b, 0 if a == b, 1 if a > b. + */ +var _compareBlankNodeObjects = function(a, b) +{ + var rval = 0; + + /* + 3. For each property, compare sorted object values. + 3.1. The bnode with fewer objects is first. + 3.2. For each object value, compare only literals and non-bnodes. + 3.2.1. The bnode with fewer non-bnodes is first. + 3.2.2. The bnode with a string object is first. + 3.2.3. The bnode with the alphabetically-first string is first. + 3.2.4. The bnode with a @literal is first. + 3.2.5. The bnode with the alphabetically-first @literal is first. + 3.2.6. The bnode with the alphabetically-first @type is first. + 3.2.7. The bnode with a @language is first. + 3.2.8. The bnode with the alphabetically-first @language is first. + 3.2.9. The bnode with the alphabetically-first @id is first. + */ + + for(var p in a) + { + // skip IDs (IRIs) + if(p !== '@id') { - // skip IDs (IRIs) - if(p !== '@id') - { - // step #3.1 - var lenA = (a[p].constructor === Array) ? a[p].length : 1; - var lenB = (b[p].constructor === Array) ? b[p].length : 1; - rval = _compare(lenA, lenB); - - // step #3.2.1 - if(rval === 0) - { + // step #3.1 + var lenA = (a[p].constructor === Array) ? a[p].length : 1; + var lenB = (b[p].constructor === Array) ? b[p].length : 1; + rval = _compare(lenA, lenB); + + // step #3.2.1 + if(rval === 0) + { // normalize objects to an array var objsA = a[p]; var objsB = b[p]; if(objsA.constructor !== Array) { - objsA = [objsA]; - objsB = [objsB]; + objsA = [objsA]; + objsB = [objsB]; } - + // compare non-bnodes (remove bnodes from comparison) objsA = objsA.filter(function(e) {return !_isNamedBlankNode(e);}); objsB = objsB.filter(function(e) {return !_isNamedBlankNode(e);}); rval = _compare(objsA.length, objsB.length); - } - - // steps #3.2.2-3.2.9 - if(rval === 0) - { + } + + // steps #3.2.2-3.2.9 + if(rval === 0) + { objsA.sort(_compareObjects); objsB.sort(_compareObjects); for(var i = 0; i < objsA.length && rval === 0; ++i) { - rval = _compareObjects(objsA[i], objsB[i]); + rval = _compareObjects(objsA[i], objsB[i]); } - } - - if(rval !== 0) - { + } + + if(rval !== 0) + { break; - } - } + } } - - return rval; - }; - - /** - * Creates a blank node name generator using the given prefix for the - * blank nodes. - * - * @param prefix the prefix to use. - * - * @return the blank node name generator. - */ - var _createNameGenerator = function(prefix) - { - var count = -1; - var ng = { - next: function() - { - ++count; - return ng.current(); - }, - current: function() - { - return '_:' + prefix + count; - }, - inNamespace: function(iri) - { - return iri.indexOf('_:' + prefix) === 0; - } - }; - return ng; - }; - - /** - * Populates a map of all named subjects from the given input and an array - * of all unnamed bnodes (includes embedded ones). - * - * @param input the input (must be expanded, no context). - * @param subjects the subjects map to populate. - * @param bnodes the bnodes array to populate. - */ - var _collectSubjects = function(input, subjects, bnodes) - { - if(input === null) + } + + return rval; +}; + +/** + * Creates a blank node name generator using the given prefix for the + * blank nodes. + * + * @param prefix the prefix to use. + * + * @return the blank node name generator. + */ +var _createNameGenerator = function(prefix) +{ + var count = -1; + var ng = { + next: function() + { + ++count; + return ng.current(); + }, + current: function() + { + return '_:' + prefix + count; + }, + inNamespace: function(iri) { - // nothing to collect + return iri.indexOf('_:' + prefix) === 0; } - else if(input.constructor === Array) + }; + return ng; +}; + +/** + * Populates a map of all named subjects from the given input and an array + * of all unnamed bnodes (includes embedded ones). + * + * @param input the input (must be expanded, no context). + * @param subjects the subjects map to populate. + * @param bnodes the bnodes array to populate. + */ +var _collectSubjects = function(input, subjects, bnodes) +{ + if(input === null) + { + // nothing to collect + } + else if(input.constructor === Array) + { + for(var i in input) { - for(var i in input) - { - _collectSubjects(input[i], subjects, bnodes); - } + _collectSubjects(input[i], subjects, bnodes); } - else if(input.constructor === Object) + } + else if(input.constructor === Object) + { + if('@id' in input) { - if('@id' in input) - { - // graph literal/disjoint graph - if(input['@id'].constructor == Array) - { + // graph literal/disjoint graph + if(input['@id'].constructor == Array) + { _collectSubjects(input['@id'], subjects, bnodes); - } - // named subject - else if(_isSubject(input)) - { + } + // named subject + else if(_isSubject(input)) + { subjects[input['@id']] = input; - } - } - // unnamed blank node - else if(_isBlankNode(input)) - { - bnodes.push(input); - } - - // recurse through subject properties - for(var key in input) - { - _collectSubjects(input[key], subjects, bnodes); - } + } } - }; - - /** - * Flattens the given value into a map of unique subjects. It is assumed that - * all blank nodes have been uniquely named before this call. Array values for - * properties will be sorted. - * - * @param parent the value's parent, NULL for none. - * @param parentProperty the property relating the value to the parent. - * @param value the value to flatten. - * @param subjects the map of subjects to write to. - */ - var _flatten = function(parent, parentProperty, value, subjects) - { - var flattened = null; - - if(value === null) + // unnamed blank node + else if(_isBlankNode(input)) { - // drop null values + bnodes.push(input); } - else if(value.constructor === Array) + + // recurse through subject properties + for(var key in input) { - // list of objects or a disjoint graph - for(var i in value) - { - _flatten(parent, parentProperty, value[i], subjects); - } + _collectSubjects(input[key], subjects, bnodes); } - else if(value.constructor === Object) + } +}; + +/** + * Flattens the given value into a map of unique subjects. It is assumed that + * all blank nodes have been uniquely named before this call. Array values for + * properties will be sorted. + * + * @param parent the value's parent, NULL for none. + * @param parentProperty the property relating the value to the parent. + * @param value the value to flatten. + * @param subjects the map of subjects to write to. + */ +var _flatten = function(parent, parentProperty, value, subjects) +{ + var flattened = null; + + if(value === null) + { + // drop null values + } + else if(value.constructor === Array) + { + // list of objects or a disjoint graph + for(var i in value) + { + _flatten(parent, parentProperty, value[i], subjects); + } + } + else if(value.constructor === Object) + { + // already-expanded value or special-case reference-only @type + if('@literal' in value || parentProperty === '@type') { - // already-expanded value or special-case reference-only @type - if('@literal' in value || parentProperty === '@type') - { - flattened = _clone(value); - } - // graph literal/disjoint graph - else if(value['@id'].constructor === Array) - { - // cannot flatten embedded graph literals - if(parent !== null) - { + flattened = _clone(value); + } + // graph literal/disjoint graph + else if(value['@id'].constructor === Array) + { + // cannot flatten embedded graph literals + if(parent !== null) + { throw { - message: 'Embedded graph literals cannot be flattened.' + message: 'Embedded graph literals cannot be flattened.' }; - } - - // top-level graph literal - for(var idx in value['@id']) - { + } + + // top-level graph literal + for(var idx in value['@id']) + { _flatten(parent, parentProperty, value['@id'][idx], subjects); - } - } - // regular subject - else - { - // create or fetch existing subject - var subject; - if(value['@id'] in subjects) - { + } + } + // regular subject + else + { + // create or fetch existing subject + var subject; + if(value['@id'] in subjects) + { // FIXME: '@id' might be a graph literal (as {}) subject = subjects[value['@id']]; - } - else - { + } + else + { // FIXME: '@id' might be a graph literal (as {}) subject = {'@id': value['@id']}; subjects[value['@id']] = subject; - } - flattened = {'@id': subject['@id']}; + } + flattened = {'@id': subject['@id']}; - // flatten embeds - for(var key in value) - { + // flatten embeds + for(var key in value) + { var v = value[key]; - + // drop null values, skip @id (it is already set above) if(v !== null && key !== '@id') { - if(key in subject) - { - if(subject[key].constructor !== Array) - { - subject[key] = [subject[key]]; - } - } - else - { - subject[key] = []; - } - - _flatten(subject[key], key, v, subjects); - if(subject[key].length === 1) - { - // convert subject[key] to object if it has only 1 - subject[key] = subject[key][0]; - } + if(key in subject) + { + if(subject[key].constructor !== Array) + { + subject[key] = [subject[key]]; + } + } + else + { + subject[key] = []; + } + + _flatten(subject[key], key, v, subjects); + if(subject[key].length === 1) + { + // convert subject[key] to object if it has only 1 + subject[key] = subject[key][0]; + } } - } - } - } - // string value - else - { - flattened = value; + } } + } + // string value + else + { + flattened = value; + } - // add flattened value to parent - if(flattened !== null && parent !== null) + // add flattened value to parent + if(flattened !== null && parent !== null) + { + if(parent.constructor === Array) { - if(parent.constructor === Array) - { - // do not add duplicate IRIs for the same property - var duplicate = false; - if(flattened.constructor === Object && '@id' in flattened) - { + // do not add duplicate IRIs for the same property + var duplicate = false; + if(flattened.constructor === Object && '@id' in flattened) + { duplicate = (parent.filter(function(e) { - return (e.constructor === Object && '@id' in e && - e['@id'] === flattened['@id']); + return (e.constructor === Object && '@id' in e && + e['@id'] === flattened['@id']); }).length > 0); - } - if(!duplicate) - { + } + if(!duplicate) + { parent.push(flattened); - } - } - else - { - parent[parentProperty] = flattened; - } + } } - }; - - - /** - * Assigns unique names to blank nodes that are unnamed in the given input. - * - * @param input the input to assign names to. - */ - Processor.prototype.nameBlankNodes = function(input) - { - // create temporary blank node name generator - var ng = this.ng.tmp = _createNameGenerator('tmp'); - - // collect subjects and unnamed bnodes - var subjects = {}; - var bnodes = []; - _collectSubjects(input, subjects, bnodes); - - // uniquely name all unnamed bnodes - for(var i in bnodes) + else { - var bnode = bnodes[i]; - if(!('@id' in bnode)) - { - // generate names until one is unique - while(ng.next() in subjects){} - bnode['@id'] = ng.current(); - subjects[ng.current()] = bnode; - } + parent[parentProperty] = flattened; } - }; - - /** - * Renames a blank node, changing its references, etc. The method assumes - * that the given name is unique. - * - * @param b the blank node to rename. - * @param id the new name to use. - */ - Processor.prototype.renameBlankNode = function(b, id) - { - var old = b['@id']; - - // update bnode IRI - b['@id'] = id; - - // update subjects map - var subjects = this.subjects; - subjects[id] = subjects[old]; - delete subjects[old]; - - // update reference and property lists - this.edges.refs[id] = this.edges.refs[old]; - this.edges.props[id] = this.edges.props[old]; - delete this.edges.refs[old]; - delete this.edges.props[old]; - - // update references to this bnode - var refs = this.edges.refs[id].all; - for(var i in refs) + } +}; + + +/** + * Assigns unique names to blank nodes that are unnamed in the given input. + * + * @param input the input to assign names to. + */ +Processor.prototype.nameBlankNodes = function(input) +{ + // create temporary blank node name generator + var ng = this.ng.tmp = _createNameGenerator('tmp'); + + // collect subjects and unnamed bnodes + var subjects = {}; + var bnodes = []; + _collectSubjects(input, subjects, bnodes); + + // uniquely name all unnamed bnodes + for(var i in bnodes) + { + var bnode = bnodes[i]; + if(!('@id' in bnode)) + { + // generate names until one is unique + while(ng.next() in subjects){} + bnode['@id'] = ng.current(); + subjects[ng.current()] = bnode; + } + } +}; + +/** + * Renames a blank node, changing its references, etc. The method assumes + * that the given name is unique. + * + * @param b the blank node to rename. + * @param id the new name to use. + */ +Processor.prototype.renameBlankNode = function(b, id) +{ + var old = b['@id']; + + // update bnode IRI + b['@id'] = id; + + // update subjects map + var subjects = this.subjects; + subjects[id] = subjects[old]; + delete subjects[old]; + + // update reference and property lists + this.edges.refs[id] = this.edges.refs[old]; + this.edges.props[id] = this.edges.props[old]; + delete this.edges.refs[old]; + delete this.edges.props[old]; + + // update references to this bnode + var refs = this.edges.refs[id].all; + for(var i in refs) + { + var iri = refs[i].s; + if(iri === old) { - var iri = refs[i].s; - if(iri === old) - { - iri = id; - } - var ref = subjects[iri]; - var props = this.edges.props[iri].all; - for(var i2 in props) - { - if(props[i2].s === old) - { + iri = id; + } + var ref = subjects[iri]; + var props = this.edges.props[iri].all; + for(var i2 in props) + { + if(props[i2].s === old) + { props[i2].s = id; - + // normalize property to array for single code-path var p = props[i2].p; var tmp = (ref[p].constructor === Object) ? [ref[p]] : - (ref[p].constructor === Array) ? ref[p] : []; + (ref[p].constructor === Array) ? ref[p] : []; for(var n in tmp) { - if(tmp[n].constructor === Object && - '@id' in tmp[n] && tmp[n]['@id'] === old) - { - tmp[n]['@id'] = id; - } + if(tmp[n].constructor === Object && + '@id' in tmp[n] && tmp[n]['@id'] === old) + { + tmp[n]['@id'] = id; + } } - } - } + } } - - // update references from this bnode - var props = this.edges.props[id].all; - for(var i in props) + } + + // update references from this bnode + var props = this.edges.props[id].all; + for(var i in props) + { + var iri = props[i].s; + refs = this.edges.refs[iri].all; + for(var r in refs) { - var iri = props[i].s; - refs = this.edges.refs[iri].all; - for(var r in refs) - { - if(refs[r].s === old) - { + if(refs[r].s === old) + { refs[r].s = id; - } - } + } } - }; - - /** - * Canonically names blank nodes in the given input. - * - * @param input the flat input graph to assign names to. - */ - Processor.prototype.canonicalizeBlankNodes = function(input) - { - // create serialization state - this.renamed = {}; - this.mappings = {}; - this.serializations = {}; - - // collect subjects and bnodes from flat input graph - var edges = this.edges = + } +}; + +/** + * Canonically names blank nodes in the given input. + * + * @param input the flat input graph to assign names to. + */ +Processor.prototype.canonicalizeBlankNodes = function(input) +{ + // create serialization state + this.renamed = {}; + this.mappings = {}; + this.serializations = {}; + + // collect subjects and bnodes from flat input graph + var edges = this.edges = + { + refs: {}, + props: {} + }; + var subjects = this.subjects = {}; + var bnodes = []; + for(var i in input) + { + var iri = input[i]['@id']; + subjects[iri] = input[i]; + edges.refs[iri] = { - refs: {}, - props: {} + all: [], + bnodes: [] }; - var subjects = this.subjects = {}; - var bnodes = []; - for(var i in input) + edges.props[iri] = { - var iri = input[i]['@id']; - subjects[iri] = input[i]; - edges.refs[iri] = - { - all: [], - bnodes: [] - }; - edges.props[iri] = - { - all: [], - bnodes: [] - }; - if(_isBlankNodeIri(iri)) - { - bnodes.push(input[i]); - } + all: [], + bnodes: [] + }; + if(_isBlankNodeIri(iri)) + { + bnodes.push(input[i]); } - - // collect edges in the graph - this.collectEdges(); - - // create canonical blank node name generator - var c14n = this.ng.c14n = _createNameGenerator('c14n'); - var ngTmp = this.ng.tmp; - - // rename all bnodes that happen to be in the c14n namespace - // and initialize serializations - for(var i in bnodes) + } + + // collect edges in the graph + this.collectEdges(); + + // create canonical blank node name generator + var c14n = this.ng.c14n = _createNameGenerator('c14n'); + var ngTmp = this.ng.tmp; + + // rename all bnodes that happen to be in the c14n namespace + // and initialize serializations + for(var i in bnodes) + { + var bnode = bnodes[i]; + var iri = bnode['@id']; + if(c14n.inNamespace(iri)) { - var bnode = bnodes[i]; - var iri = bnode['@id']; - if(c14n.inNamespace(iri)) - { - // generate names until one is unique - while(ngTmp.next() in subjects){}; - this.renameBlankNode(bnode, ngTmp.current()); - iri = bnode['@id']; - } - this.serializations[iri] = - { - 'props': null, - 'refs': null - }; + // generate names until one is unique + while(ngTmp.next() in subjects){}; + this.renameBlankNode(bnode, ngTmp.current()); + iri = bnode['@id']; } - - // keep sorting and naming blank nodes until they are all named - var resort = true; - var self = this; - while(bnodes.length > 0) + this.serializations[iri] = + { + 'props': null, + 'refs': null + }; + } + + // keep sorting and naming blank nodes until they are all named + var resort = true; + var self = this; + while(bnodes.length > 0) + { + if(resort) { - if(resort) - { - resort = false; - bnodes.sort(function(a, b) - { + resort = false; + bnodes.sort(function(a, b) + { return self.deepCompareBlankNodes(a, b); - }); - } - - // name all bnodes according to the first bnode's relation mappings - var bnode = bnodes.shift(); - var iri = bnode['@id']; - var dirs = ['props', 'refs']; - for(var d in dirs) - { - var dir = dirs[d]; - - // if no serialization has been computed, name only the first node - if(this.serializations[iri][dir] === null) - { + }); + } + + // name all bnodes according to the first bnode's relation mappings + var bnode = bnodes.shift(); + var iri = bnode['@id']; + var dirs = ['props', 'refs']; + for(var d in dirs) + { + var dir = dirs[d]; + + // if no serialization has been computed, name only the first node + if(this.serializations[iri][dir] === null) + { var mapping = {}; mapping[iri] = 's1'; - } - else - { + } + else + { mapping = this.serializations[iri][dir].m; - } - - // sort keys by value to name them in order - var keys = Object.keys(mapping); - keys.sort(function(a, b) - { + } + + // sort keys by value to name them in order + var keys = Object.keys(mapping); + keys.sort(function(a, b) + { return _compare(mapping[a], mapping[b]); - }); - - // name bnodes in mapping - var renamed = []; - for(var i in keys) - { + }); + + // name bnodes in mapping + var renamed = []; + for(var i in keys) + { var iriK = keys[i]; if(!c14n.inNamespace(iri) && iriK in subjects) { - this.renameBlankNode(subjects[iriK], c14n.next()); - renamed.push(iriK); + this.renameBlankNode(subjects[iriK], c14n.next()); + renamed.push(iriK); } - } - - // only keep non-canonically named bnodes - var tmp = bnodes; - bnodes = []; - for(var i in tmp) - { + } + + // only keep non-canonically named bnodes + var tmp = bnodes; + bnodes = []; + for(var i in tmp) + { var b = tmp[i]; var iriB = b['@id']; if(!c14n.inNamespace(iriB)) { - // mark serializations related to the named bnodes as dirty - for(var i2 in renamed) - { - if(this.markSerializationDirty(iriB, renamed[i2], dir)) - { - // resort if a serialization was marked dirty - resort = true; - } - } - bnodes.push(b); + // mark serializations related to the named bnodes as dirty + for(var i2 in renamed) + { + if(this.markSerializationDirty(iriB, renamed[i2], dir)) + { + // resort if a serialization was marked dirty + resort = true; + } + } + bnodes.push(b); } - } - } + } } - - // sort property lists that now have canonically-named bnodes - for(var key in edges.props) + } + + // sort property lists that now have canonically-named bnodes + for(var key in edges.props) + { + if(edges.props[key].bnodes.length > 0) { - if(edges.props[key].bnodes.length > 0) - { - var bnode = subjects[key]; - for(var p in bnode) - { + var bnode = subjects[key]; + for(var p in bnode) + { if(p.indexOf('@') !== 0 && bnode[p].constructor === Array) { - bnode[p].sort(_compareObjects); + bnode[p].sort(_compareObjects); } - } - } + } } - }; - - /** - * A MappingBuilder is used to build a mapping of existing blank node names - * to a form for serialization. The serialization is used to compare blank - * nodes against one another to determine a sort order. - */ - MappingBuilder = function() - { - this.count = 1; - this.processed = {}; - this.mapping = {}; - this.adj = {}; - this.keyStack = [{ keys: ['s1'], idx: 0 }]; - this.done = {}; - this.s = ''; - }; - - /** - * Copies this MappingBuilder. - * - * @return the MappingBuilder copy. - */ - MappingBuilder.prototype.copy = function() - { - var rval = new MappingBuilder(); - rval.count = this.count; - rval.processed = _clone(this.processed); - rval.mapping = _clone(this.mapping); - rval.adj = _clone(this.adj); - rval.keyStack = _clone(this.keyStack); - rval.done = _clone(this.done); - rval.s = this.s; - return rval; - }; - - /** - * Maps the next name to the given bnode IRI if the bnode IRI isn't already in - * the mapping. If the given bnode IRI is canonical, then it will be given - * a shortened form of the same name. - * - * @param iri the blank node IRI to map the next name to. - * - * @return the mapped name. - */ - MappingBuilder.prototype.mapNode = function(iri) - { - if(!(iri in this.mapping)) + } +}; + +/** + * A MappingBuilder is used to build a mapping of existing blank node names + * to a form for serialization. The serialization is used to compare blank + * nodes against one another to determine a sort order. + */ +MappingBuilder = function() +{ + this.count = 1; + this.processed = {}; + this.mapping = {}; + this.adj = {}; + this.keyStack = [{ keys: ['s1'], idx: 0 }]; + this.done = {}; + this.s = ''; +}; + +/** + * Copies this MappingBuilder. + * + * @return the MappingBuilder copy. + */ +MappingBuilder.prototype.copy = function() +{ + var rval = new MappingBuilder(); + rval.count = this.count; + rval.processed = _clone(this.processed); + rval.mapping = _clone(this.mapping); + rval.adj = _clone(this.adj); + rval.keyStack = _clone(this.keyStack); + rval.done = _clone(this.done); + rval.s = this.s; + return rval; +}; + +/** + * Maps the next name to the given bnode IRI if the bnode IRI isn't already in + * the mapping. If the given bnode IRI is canonical, then it will be given + * a shortened form of the same name. + * + * @param iri the blank node IRI to map the next name to. + * + * @return the mapped name. + */ +MappingBuilder.prototype.mapNode = function(iri) +{ + if(!(iri in this.mapping)) + { + if(iri.indexOf('_:c14n') === 0) { - if(iri.indexOf('_:c14n') === 0) - { - this.mapping[iri] = 'c' + iri.substr(6); - } - else - { - this.mapping[iri] = 's' + this.count++; - } + this.mapping[iri] = 'c' + iri.substr(6); } - return this.mapping[iri]; - }; - - /** - * Serializes the properties of the given bnode for its relation serialization. - * - * @param b the blank node. - * - * @return the serialized properties. - */ - var _serializeProperties = function(b) - { - var rval = ''; - - var first = true; - for(var p in b) + else + { + this.mapping[iri] = 's' + this.count++; + } + } + return this.mapping[iri]; +}; + +/** + * Serializes the properties of the given bnode for its relation serialization. + * + * @param b the blank node. + * + * @return the serialized properties. + */ +var _serializeProperties = function(b) +{ + var rval = ''; + + var first = true; + for(var p in b) + { + if(p !== '@id') { - if(p !== '@id') - { - if(first) - { + if(first) + { first = false; - } - else - { + } + else + { rval += '|'; - } - - // property - rval += '<' + p + '>'; - - // object(s) - var objs = (b[p].constructor === Array) ? b[p] : [b[p]]; - for(var oi in objs) - { + } + + // property + rval += '<' + p + '>'; + + // object(s) + var objs = (b[p].constructor === Array) ? b[p] : [b[p]]; + for(var oi in objs) + { var o = objs[oi]; if(o.constructor === Object) { - // ID (IRI) - if('@id' in o) - { - if(_isBlankNodeIri(o['@id'])) - { - rval += '_:'; - } - else - { - rval += '<' + o['@id'] + '>'; - } - } - // literal - else - { - rval += '"' + o['@literal'] + '"'; - - // type literal - if('@type' in o) - { - rval += '^^<' + o['@type'] + '>'; - } - // language literal - else if('@language' in o) - { - rval += '@' + o['@language']; - } - } + // ID (IRI) + if('@id' in o) + { + if(_isBlankNodeIri(o['@id'])) + { + rval += '_:'; + } + else + { + rval += '<' + o['@id'] + '>'; + } + } + // literal + else + { + rval += '"' + o['@literal'] + '"'; + + // type literal + if('@type' in o) + { + rval += '^^<' + o['@type'] + '>'; + } + // language literal + else if('@language' in o) + { + rval += '@' + o['@language']; + } + } } // plain literal else { - rval += '"' + o + '"'; + rval += '"' + o + '"'; } - } - } + } } - - return rval; - }; - - /** - * Recursively increments the relation serialization for a mapping. - * - * @param subjects the subjects in the graph. - * @param edges the edges in the graph. - */ - MappingBuilder.prototype.serialize = function(subjects, edges) - { - if(this.keyStack.length > 0) + } + + return rval; +}; + +/** + * Recursively increments the relation serialization for a mapping. + * + * @param subjects the subjects in the graph. + * @param edges the edges in the graph. + */ +MappingBuilder.prototype.serialize = function(subjects, edges) +{ + if(this.keyStack.length > 0) + { + // continue from top of key stack + var next = this.keyStack.pop(); + for(; next.idx < next.keys.length; ++next.idx) { - // continue from top of key stack - var next = this.keyStack.pop(); - for(; next.idx < next.keys.length; ++next.idx) - { - var k = next.keys[next.idx]; - if(!(k in this.adj)) - { + var k = next.keys[next.idx]; + if(!(k in this.adj)) + { this.keyStack.push(next); break; - } - - if(k in this.done) - { + } + + if(k in this.done) + { // mark cycle this.s += '_' + k; - } - else - { + } + else + { // mark key as serialized this.done[k] = true; - + // serialize top-level key and its details var s = k; var adj = this.adj[k]; var iri = adj.i; if(iri in subjects) { - var b = subjects[iri]; - - // serialize properties - s += '[' + _serializeProperties(b) + ']'; - - // serialize references - var first = true; - s += '['; - var refs = edges.refs[iri].all; - for(var r in refs) - { - if(first) - { - first = false; - } - else - { - s += '|'; - } - s += '<' + refs[r].p + '>'; - s += _isBlankNodeIri(refs[r].s) ? - '_:' : ('<' + refs[r].s + '>'); - } - s += ']'; + var b = subjects[iri]; + + // serialize properties + s += '[' + _serializeProperties(b) + ']'; + + // serialize references + var first = true; + s += '['; + var refs = edges.refs[iri].all; + for(var r in refs) + { + if(first) + { + first = false; + } + else + { + s += '|'; + } + s += '<' + refs[r].p + '>'; + s += _isBlankNodeIri(refs[r].s) ? + '_:' : ('<' + refs[r].s + '>'); + } + s += ']'; } - + // serialize adjacent node keys s += adj.k.join(''); this.s += s; this.keyStack.push({ keys: adj.k, idx: 0 }); this.serialize(subjects, edges); - } - } - } - }; - - /** - * Marks a relation serialization as dirty if necessary. - * - * @param iri the IRI of the bnode to check. - * @param changed the old IRI of the bnode that changed. - * @param dir the direction to check ('props' or 'refs'). - * - * @return true if marked dirty, false if not. - */ - Processor.prototype.markSerializationDirty = function(iri, changed, dir) - { - var rval = false; - - var s = this.serializations[iri]; - if(s[dir] !== null && changed in s[dir].m) - { - s[dir] = null; - rval = true; - } - - return rval; - }; - - /** - * Rotates the elements in an array one position. - * - * @param a the array. - */ - var _rotate = function(a) - { - a.unshift.apply(a, a.splice(1, a.length)); - }; - - /** - * Compares two serializations for the same blank node. If the two - * serializations aren't complete enough to determine if they are equal (or if - * they are actually equal), 0 is returned. - * - * @param s1 the first serialization. - * @param s2 the second serialization. - * - * @return -1 if s1 < s2, 0 if s1 == s2 (or indeterminate), 1 if s1 > v2. - */ - var _compareSerializations = function(s1, s2) - { - var rval = 0; - - if(s1.length == s2.length) - { - rval = _compare(s1, s2); - } - else if(s1.length > s2.length) - { - rval = _compare(s1.substr(0, s2.length), s2); - } - else - { - rval = _compare(s1, s2.substr(0, s1.length)); + } } - - return rval; - }; - - /** - * Recursively serializes adjacent bnode combinations for a bnode. - * - * @param s the serialization to update. - * @param iri the IRI of the bnode being serialized. - * @param siri the serialization name for the bnode IRI. - * @param mb the MappingBuilder to use. - * @param dir the edge direction to use ('props' or 'refs'). - * @param mapped all of the already-mapped adjacent bnodes. - * @param notMapped all of the not-yet mapped adjacent bnodes. - */ - Processor.prototype.serializeCombos = function( - s, iri, siri, mb, dir, mapped, notMapped) - { - // handle recursion - if(notMapped.length > 0) + } +}; + +/** + * Marks a relation serialization as dirty if necessary. + * + * @param iri the IRI of the bnode to check. + * @param changed the old IRI of the bnode that changed. + * @param dir the direction to check ('props' or 'refs'). + * + * @return true if marked dirty, false if not. + */ +Processor.prototype.markSerializationDirty = function(iri, changed, dir) +{ + var rval = false; + + var s = this.serializations[iri]; + if(s[dir] !== null && changed in s[dir].m) + { + s[dir] = null; + rval = true; + } + + return rval; +}; + +/** + * Rotates the elements in an array one position. + * + * @param a the array. + */ +var _rotate = function(a) +{ + a.unshift.apply(a, a.splice(1, a.length)); +}; + +/** + * Compares two serializations for the same blank node. If the two + * serializations aren't complete enough to determine if they are equal (or if + * they are actually equal), 0 is returned. + * + * @param s1 the first serialization. + * @param s2 the second serialization. + * + * @return -1 if s1 < s2, 0 if s1 == s2 (or indeterminate), 1 if s1 > v2. + */ +var _compareSerializations = function(s1, s2) +{ + var rval = 0; + + if(s1.length == s2.length) + { + rval = _compare(s1, s2); + } + else if(s1.length > s2.length) + { + rval = _compare(s1.substr(0, s2.length), s2); + } + else + { + rval = _compare(s1, s2.substr(0, s1.length)); + } + + return rval; +}; + +/** + * Recursively serializes adjacent bnode combinations for a bnode. + * + * @param s the serialization to update. + * @param iri the IRI of the bnode being serialized. + * @param siri the serialization name for the bnode IRI. + * @param mb the MappingBuilder to use. + * @param dir the edge direction to use ('props' or 'refs'). + * @param mapped all of the already-mapped adjacent bnodes. + * @param notMapped all of the not-yet mapped adjacent bnodes. + */ +Processor.prototype.serializeCombos = function( + s, iri, siri, mb, dir, mapped, notMapped) +{ + // handle recursion + if(notMapped.length > 0) + { + // copy mapped nodes + mapped = _clone(mapped); + + // map first bnode in list + mapped[mb.mapNode(notMapped[0].s)] = notMapped[0].s; + + // recurse into remaining possible combinations + var original = mb.copy(); + notMapped = notMapped.slice(1); + var rotations = Math.max(1, notMapped.length); + for(var r = 0; r < rotations; ++r) { - // copy mapped nodes - mapped = _clone(mapped); - - // map first bnode in list - mapped[mb.mapNode(notMapped[0].s)] = notMapped[0].s; - - // recurse into remaining possible combinations - var original = mb.copy(); - notMapped = notMapped.slice(1); - var rotations = Math.max(1, notMapped.length); - for(var r = 0; r < rotations; ++r) - { - var m = (r === 0) ? mb : original.copy(); - this.serializeCombos(s, iri, siri, m, dir, mapped, notMapped); - - // rotate not-mapped for next combination - _rotate(notMapped); - } + var m = (r === 0) ? mb : original.copy(); + this.serializeCombos(s, iri, siri, m, dir, mapped, notMapped); + + // rotate not-mapped for next combination + _rotate(notMapped); } - // no more adjacent bnodes to map, update serialization - else + } + // no more adjacent bnodes to map, update serialization + else + { + var keys = Object.keys(mapped).sort(); + mb.adj[siri] = { i: iri, k: keys, m: mapped }; + mb.serialize(this.subjects, this.edges); + + // optimize away mappings that are already too large + if(s[dir] === null || _compareSerializations(mb.s, s[dir].s) <= 0) { - var keys = Object.keys(mapped).sort(); - mb.adj[siri] = { i: iri, k: keys, m: mapped }; - mb.serialize(this.subjects, this.edges); - - // optimize away mappings that are already too large - if(s[dir] === null || _compareSerializations(mb.s, s[dir].s) <= 0) - { - // recurse into adjacent values - for(var i in keys) - { + // recurse into adjacent values + for(var i in keys) + { var k = keys[i]; this.serializeBlankNode(s, mapped[k], mb, dir); - } - - // update least serialization if new one has been found - mb.serialize(this.subjects, this.edges); - if(s[dir] === null || + } + + // update least serialization if new one has been found + mb.serialize(this.subjects, this.edges); + if(s[dir] === null || (_compareSerializations(mb.s, s[dir].s) <= 0 && - mb.s.length >= s[dir].s.length)) - { + mb.s.length >= s[dir].s.length)) + { s[dir] = { s: mb.s, m: mb.mapping }; - } - } + } } - }; - - /** - * Computes the relation serialization for the given blank node IRI. - * - * @param s the serialization to update. - * @param iri the current bnode IRI to be mapped. - * @param mb the MappingBuilder to use. - * @param dir the edge direction to use ('props' or 'refs'). - */ - Processor.prototype.serializeBlankNode = function(s, iri, mb, dir) - { - // only do mapping if iri not already processed - if(!(iri in mb.processed)) + } +}; + +/** + * Computes the relation serialization for the given blank node IRI. + * + * @param s the serialization to update. + * @param iri the current bnode IRI to be mapped. + * @param mb the MappingBuilder to use. + * @param dir the edge direction to use ('props' or 'refs'). + */ +Processor.prototype.serializeBlankNode = function(s, iri, mb, dir) +{ + // only do mapping if iri not already processed + if(!(iri in mb.processed)) + { + // iri now processed + mb.processed[iri] = true; + var siri = mb.mapNode(iri); + + // copy original mapping builder + var original = mb.copy(); + + // split adjacent bnodes on mapped and not-mapped + var adj = this.edges[dir][iri].bnodes; + var mapped = {}; + var notMapped = []; + for(var i in adj) { - // iri now processed - mb.processed[iri] = true; - var siri = mb.mapNode(iri); - - // copy original mapping builder - var original = mb.copy(); - - // split adjacent bnodes on mapped and not-mapped - var adj = this.edges[dir][iri].bnodes; - var mapped = {}; - var notMapped = []; - for(var i in adj) - { - if(adj[i].s in mb.mapping) - { + if(adj[i].s in mb.mapping) + { mapped[mb.mapping[adj[i].s]] = adj[i].s; - } - else - { - notMapped.push(adj[i]); - } - } - - /* - // TODO: sort notMapped using ShallowCompare - var self = this; - notMapped.sort(function(a, b) + } + else { + notMapped.push(adj[i]); + } + } + + /* + // TODO: sort notMapped using ShallowCompare + var self = this; + notMapped.sort(function(a, b) + { var rval = self.shallowCompareBlankNodes( - self.subjects[a.s], self.subjects[b.s]); + self.subjects[a.s], self.subjects[b.s]); return rval; - }); - - var same = false; - var prev = null; - for(var i in notMapped) - { + }); + + var same = false; + var prev = null; + for(var i in notMapped) + { var curr = this.subjects[notMapped[i].s]; if(prev !== null) { - if(this.shallowCompareBlankNodes(prev, curr) === 0) - { - same = true; - } - else - { - if(!same) - { - mapped[mb.mapNode(prev['@id'])] = prev['@id']; - delete notMapped[i - 1]; - } - if(i === notMapped.length - 1) - { - mapped[mb.mapNode(curr['@id'])]; - delete notMapped[i]; - } - same = false; - } + if(this.shallowCompareBlankNodes(prev, curr) === 0) + { + same = true; + } + else + { + if(!same) + { + mapped[mb.mapNode(prev['@id'])] = prev['@id']; + delete notMapped[i - 1]; + } + if(i === notMapped.length - 1) + { + mapped[mb.mapNode(curr['@id'])]; + delete notMapped[i]; + } + same = false; + } } prev = curr; - }*/ - - // TODO: ensure this optimization does not alter canonical order - - // if the current bnode already has a serialization, reuse it - /*var hint = (iri in this.serializations) ? + }*/ + + // TODO: ensure this optimization does not alter canonical order + + // if the current bnode already has a serialization, reuse it + /*var hint = (iri in this.serializations) ? this.serializations[iri][dir] : null; - if(hint !== null) - { + if(hint !== null) + { var hm = hint.m; notMapped.sort(function(a, b) { - return _compare(hm[a.s], hm[b.s]); + return _compare(hm[a.s], hm[b.s]); }); for(var i in notMapped) { - mapped[mb.mapNode(notMapped[i].s)] = notMapped[i].s; + mapped[mb.mapNode(notMapped[i].s)] = notMapped[i].s; } notMapped = []; - }*/ - - // loop over possible combinations - var combos = Math.max(1, notMapped.length); - for(var i = 0; i < combos; ++i) - { - var m = (i === 0) ? mb : original.copy(); - this.serializeCombos(s, iri, siri, m, dir, mapped, notMapped); - } - } - }; - - /** - * Compares two blank nodes for equivalence. - * - * @param a the first blank node. - * @param b the second blank node. - * - * @return -1 if a < b, 0 if a == b, 1 if a > b. - */ - Processor.prototype.deepCompareBlankNodes = function(a, b) - { - var rval = 0; - - // compare IRIs - var iriA = a['@id']; - var iriB = b['@id']; - if(iriA === iriB) + }*/ + + // loop over possible combinations + var combos = Math.max(1, notMapped.length); + for(var i = 0; i < combos; ++i) { - rval = 0; + var m = (i === 0) ? mb : original.copy(); + this.serializeCombos(s, iri, siri, m, dir, mapped, notMapped); } - else + } +}; + +/** + * Compares two blank nodes for equivalence. + * + * @param a the first blank node. + * @param b the second blank node. + * + * @return -1 if a < b, 0 if a == b, 1 if a > b. + */ +Processor.prototype.deepCompareBlankNodes = function(a, b) +{ + var rval = 0; + + // compare IRIs + var iriA = a['@id']; + var iriB = b['@id']; + if(iriA === iriB) + { + rval = 0; + } + else + { + // do shallow compare first + rval = this.shallowCompareBlankNodes(a, b); + + // deep comparison is necessary + if(rval === 0) { - // do shallow compare first - rval = this.shallowCompareBlankNodes(a, b); - - // deep comparison is necessary - if(rval === 0) - { - // compare property edges and then reference edges - var dirs = ['props', 'refs']; - for(var i = 0; rval === 0 && i < dirs.length; ++i) - { + // compare property edges and then reference edges + var dirs = ['props', 'refs']; + for(var i = 0; rval === 0 && i < dirs.length; ++i) + { // recompute 'a' and 'b' serializations as necessary var dir = dirs[i]; var sA = this.serializations[iriA]; var sB = this.serializations[iriB]; if(sA[dir] === null) { - var mb = new MappingBuilder(); - if(dir === 'refs') - { - // keep same mapping and count from 'props' serialization - mb.mapping = _clone(sA['props'].m); - mb.count = Object.keys(mb.mapping).length + 1; - } - this.serializeBlankNode(sA, iriA, mb, dir); + var mb = new MappingBuilder(); + if(dir === 'refs') + { + // keep same mapping and count from 'props' serialization + mb.mapping = _clone(sA['props'].m); + mb.count = Object.keys(mb.mapping).length + 1; + } + this.serializeBlankNode(sA, iriA, mb, dir); } if(sB[dir] === null) { - var mb = new MappingBuilder(); - if(dir === 'refs') - { - // keep same mapping and count from 'props' serialization - mb.mapping = _clone(sB['props'].m); - mb.count = Object.keys(mb.mapping).length + 1; - } - this.serializeBlankNode(sB, iriB, mb, dir); + var mb = new MappingBuilder(); + if(dir === 'refs') + { + // keep same mapping and count from 'props' serialization + mb.mapping = _clone(sB['props'].m); + mb.count = Object.keys(mb.mapping).length + 1; + } + this.serializeBlankNode(sB, iriB, mb, dir); } - + // compare serializations rval = _compare(sA[dir].s, sB[dir].s); - } - } + } } - - return rval; - }; - - /** - * Performs a shallow sort comparison on the given bnodes. - * - * @param a the first bnode. - * @param b the second bnode. - * - * @return -1 if a < b, 0 if a == b, 1 if a > b. - */ - Processor.prototype.shallowCompareBlankNodes = function(a, b) - { - var rval = 0; - - /* ShallowSort Algorithm (when comparing two bnodes): - 1. Compare the number of properties. - 1.1. The bnode with fewer properties is first. - 2. Compare alphabetically sorted-properties. - 2.1. The bnode with the alphabetically-first property is first. - 3. For each property, compare object values. - 4. Compare the number of references. - 4.1. The bnode with fewer references is first. - 5. Compare sorted references. - 5.1. The bnode with the reference iri (vs. bnode) is first. - 5.2. The bnode with the alphabetically-first reference iri is first. - 5.3. The bnode with the alphabetically-first reference property is first. - */ - var pA = Object.keys(a); - var pB = Object.keys(b); - - // step #1 - rval = _compare(pA.length, pB.length); - - // step #2 - if(rval === 0) + } + + return rval; +}; + +/** + * Performs a shallow sort comparison on the given bnodes. + * + * @param a the first bnode. + * @param b the second bnode. + * + * @return -1 if a < b, 0 if a == b, 1 if a > b. + */ +Processor.prototype.shallowCompareBlankNodes = function(a, b) +{ + var rval = 0; + + /* ShallowSort Algorithm (when comparing two bnodes): + 1. Compare the number of properties. + 1.1. The bnode with fewer properties is first. + 2. Compare alphabetically sorted-properties. + 2.1. The bnode with the alphabetically-first property is first. + 3. For each property, compare object values. + 4. Compare the number of references. + 4.1. The bnode with fewer references is first. + 5. Compare sorted references. + 5.1. The bnode with the reference iri (vs. bnode) is first. + 5.2. The bnode with the alphabetically-first reference iri is first. + 5.3. The bnode with the alphabetically-first reference property is first. + */ + var pA = Object.keys(a); + var pB = Object.keys(b); + + // step #1 + rval = _compare(pA.length, pB.length); + + // step #2 + if(rval === 0) + { + rval = _compare(pA.sort(), pB.sort()); + } + + // step #3 + if(rval === 0) + { + rval = _compareBlankNodeObjects(a, b); + } + + // step #4 + if(rval === 0) + { + var edgesA = this.edges.refs[a['@id']].all; + var edgesB = this.edges.refs[b['@id']].all; + rval = _compare(edgesA.length, edgesB.length); + } + + // step #5 + if(rval === 0) + { + for(var i = 0; i < edgesA.length && rval === 0; ++i) { - rval = _compare(pA.sort(), pB.sort()); + rval = this.compareEdges(edgesA[i], edgesB[i]); } - - // step #3 - if(rval === 0) + } + + return rval; +}; + +/** + * Compares two edges. Edges with an IRI (vs. a bnode ID) come first, then + * alphabetically-first IRIs, then alphabetically-first properties. If a blank + * node has been canonically named, then blank nodes will be compared after + * properties (with a preference for canonically named over non-canonically + * named), otherwise they won't be. + * + * @param a the first edge. + * @param b the second edge. + * + * @return -1 if a < b, 0 if a == b, 1 if a > b. + */ +Processor.prototype.compareEdges = function(a, b) +{ + var rval = 0; + + var bnodeA = _isBlankNodeIri(a.s); + var bnodeB = _isBlankNodeIri(b.s); + var c14n = this.ng.c14n; + + // if not both bnodes, one that is a bnode is greater + if(bnodeA != bnodeB) + { + rval = bnodeA ? 1 : -1; + } + else + { + if(!bnodeA) { - rval = _compareBlankNodeObjects(a, b); + rval = _compare(a.s, b.s); } - - // step #4 if(rval === 0) { - var edgesA = this.edges.refs[a['@id']].all; - var edgesB = this.edges.refs[b['@id']].all; - rval = _compare(edgesA.length, edgesB.length); + rval = _compare(a.p, b.p); } - - // step #5 - if(rval === 0) + + // do bnode IRI comparison if canonical naming has begun + if(rval === 0 && c14n !== null) { - for(var i = 0; i < edgesA.length && rval === 0; ++i) - { - rval = this.compareEdges(edgesA[i], edgesB[i]); - } + var c14nA = c14n.inNamespace(a.s); + var c14nB = c14n.inNamespace(b.s); + if(c14nA != c14nB) + { + rval = c14nA ? 1 : -1; + } + else if(c14nA) + { + rval = _compare(a.s, b.s); + } } - - return rval; - }; - - /** - * Compares two edges. Edges with an IRI (vs. a bnode ID) come first, then - * alphabetically-first IRIs, then alphabetically-first properties. If a blank - * node has been canonically named, then blank nodes will be compared after - * properties (with a preference for canonically named over non-canonically - * named), otherwise they won't be. - * - * @param a the first edge. - * @param b the second edge. - * - * @return -1 if a < b, 0 if a == b, 1 if a > b. - */ - Processor.prototype.compareEdges = function(a, b) - { - var rval = 0; - - var bnodeA = _isBlankNodeIri(a.s); - var bnodeB = _isBlankNodeIri(b.s); - var c14n = this.ng.c14n; - - // if not both bnodes, one that is a bnode is greater - if(bnodeA != bnodeB) - { - rval = bnodeA ? 1 : -1; - } - else - { - if(!bnodeA) - { - rval = _compare(a.s, b.s); - } - if(rval === 0) - { - rval = _compare(a.p, b.p); - } - - // do bnode IRI comparison if canonical naming has begun - if(rval === 0 && c14n !== null) - { - var c14nA = c14n.inNamespace(a.s); - var c14nB = c14n.inNamespace(b.s); - if(c14nA != c14nB) - { - rval = c14nA ? 1 : -1; - } - else if(c14nA) - { - rval = _compare(a.s, b.s); - } - } - } - - return rval; - }; - - /** - * Populates the given reference map with all of the subject edges in the - * graph. The references will be categorized by the direction of the edges, - * where 'props' is for properties and 'refs' is for references to a subject as - * an object. The edge direction categories for each IRI will be sorted into - * groups 'all' and 'bnodes'. - */ - Processor.prototype.collectEdges = function() - { - var refs = this.edges.refs; - var props = this.edges.props; - - // collect all references and properties - for(var iri in this.subjects) + } + + return rval; +}; + +/** + * Populates the given reference map with all of the subject edges in the + * graph. The references will be categorized by the direction of the edges, + * where 'props' is for properties and 'refs' is for references to a subject as + * an object. The edge direction categories for each IRI will be sorted into + * groups 'all' and 'bnodes'. + */ +Processor.prototype.collectEdges = function() +{ + var refs = this.edges.refs; + var props = this.edges.props; + + // collect all references and properties + for(var iri in this.subjects) + { + var subject = this.subjects[iri]; + for(var key in subject) { - var subject = this.subjects[iri]; - for(var key in subject) - { - if(key !== '@id') - { + if(key !== '@id') + { // normalize to array for single codepath var object = subject[key]; var tmp = (object.constructor !== Array) ? [object] : object; for(var i in tmp) { - var o = tmp[i]; - if(o.constructor === Object && '@id' in o && - o['@id'] in this.subjects) - { - var objIri = o['@id']; - - // map object to this subject - refs[objIri].all.push({ s: iri, p: key }); - - // map this subject to object - props[iri].all.push({ s: objIri, p: key }); - } + var o = tmp[i]; + if(o.constructor === Object && '@id' in o && + o['@id'] in this.subjects) + { + var objIri = o['@id']; + + // map object to this subject + refs[objIri].all.push({ s: iri, p: key }); + + // map this subject to object + props[iri].all.push({ s: objIri, p: key }); + } } - } - } - } - - // create sorted categories - var self = this; - for(var iri in refs) - { - refs[iri].all.sort(function(a, b) { return self.compareEdges(a, b); }); - refs[iri].bnodes = refs[iri].all.filter(function(edge) { - return _isBlankNodeIri(edge.s); - }); - } - for(var iri in props) - { - props[iri].all.sort(function(a, b) { return self.compareEdges(a, b); }); - props[iri].bnodes = props[iri].all.filter(function(edge) { - return _isBlankNodeIri(edge.s); - }); + } } - }; - - /** - * Returns true if the given input is a subject and has one of the given types - * in the given frame. - * - * @param input the input. - * @param frame the frame with types to look for. - * - * @return true if the input has one of the given types. - */ - var _isType = function(input, frame) - { - var rval = false; - - // check if type(s) are specified in frame and input - var type = '@type'; - if('@type' in frame && - input.constructor === Object && type in input) + } + + // create sorted categories + var self = this; + for(var iri in refs) + { + refs[iri].all.sort(function(a, b) { return self.compareEdges(a, b); }); + refs[iri].bnodes = refs[iri].all.filter(function(edge) { + return _isBlankNodeIri(edge.s); + }); + } + for(var iri in props) + { + props[iri].all.sort(function(a, b) { return self.compareEdges(a, b); }); + props[iri].bnodes = props[iri].all.filter(function(edge) { + return _isBlankNodeIri(edge.s); + }); + } +}; + +/** + * Returns true if the given input is a subject and has one of the given types + * in the given frame. + * + * @param input the input. + * @param frame the frame with types to look for. + * + * @return true if the input has one of the given types. + */ +var _isType = function(input, frame) +{ + var rval = false; + + // check if type(s) are specified in frame and input + var type = '@type'; + if('@type' in frame && + input.constructor === Object && type in input) + { + var tmp = (input[type].constructor === Array) ? + input[type] : [input[type]]; + var types = (frame[type].constructor === Array) ? + frame[type] : [frame[type]]; + for(var t = 0; t < types.length && !rval; ++t) { - var tmp = (input[type].constructor === Array) ? - input[type] : [input[type]]; - var types = (frame[type].constructor === Array) ? - frame[type] : [frame[type]]; - for(var t = 0; t < types.length && !rval; ++t) - { - type = types[t]; - for(var i in tmp) - { + type = types[t]; + for(var i in tmp) + { if(tmp[i] === type) { - rval = true; - break; + rval = true; + break; } - } - } + } } - - return rval; - }; - - /** - * Returns true if the given input matches the given frame via duck-typing. - * - * @param input the input. - * @param frame the frame to check against. - * - * @return true if the input matches the frame. - */ - var _isDuckType = function(input, frame) - { - var rval = false; - - // frame must not have a specific type - var type = '@type'; - if(!(type in frame)) + } + + return rval; +}; + +/** + * Returns true if the given input matches the given frame via duck-typing. + * + * @param input the input. + * @param frame the frame to check against. + * + * @return true if the input matches the frame. + */ +var _isDuckType = function(input, frame) +{ + var rval = false; + + // frame must not have a specific type + var type = '@type'; + if(!(type in frame)) + { + // get frame properties that must exist on input + var props = Object.keys(frame).filter(function(e) { - // get frame properties that must exist on input - var props = Object.keys(frame).filter(function(e) - { - // filter non-keywords - return e.indexOf('@') !== 0; - }); - if(props.length === 0) - { - // input always matches if there are no properties - rval = true; - } - // input must be a subject with all the given properties - else if(input.constructor === Object && '@id' in input) - { - rval = true; - for(var i in props) - { + // filter non-keywords + return e.indexOf('@') !== 0; + }); + if(props.length === 0) + { + // input always matches if there are no properties + rval = true; + } + // input must be a subject with all the given properties + else if(input.constructor === Object && '@id' in input) + { + rval = true; + for(var i in props) + { if(!(props[i] in input)) { - rval = false; - break; + rval = false; + break; } - } - } + } } - - return rval; - }; - - /** - * Subframes a value. - * - * @param subjects a map of subjects in the graph. - * @param value the value to subframe. - * @param frame the frame to use. - * @param embeds a map of previously embedded subjects, used to prevent cycles. - * @param autoembed true if auto-embed is on, false if not. - * @param parent the parent object. - * @param parentKey the parent key. - * @param options the framing options. - * - * @return the framed input. - */ - var _subframe = function( - subjects, value, frame, embeds, autoembed, parent, parentKey, options) - { - // get existing embed entry - var iri = value['@id']; - var embed = (iri in embeds) ? embeds[iri] : null; - - // determine if value should be embedded or referenced, - // embed is ON if: - // 1. The frame OR default option specifies @embed as ON, AND - // 2. There is no existing embed OR it is an autoembed, AND - // autoembed mode is off. - var embedOn = ( - (('@embed' in frame && frame['@embed']) || - (!('@embed' in frame) && options.defaults.embedOn)) && - (embed === null || (embed.autoembed && !autoembed))); - - if(!embedOn) + } + + return rval; +}; + +/** + * Subframes a value. + * + * @param subjects a map of subjects in the graph. + * @param value the value to subframe. + * @param frame the frame to use. + * @param embeds a map of previously embedded subjects, used to prevent cycles. + * @param autoembed true if auto-embed is on, false if not. + * @param parent the parent object. + * @param parentKey the parent key. + * @param options the framing options. + * + * @return the framed input. + */ +var _subframe = function( + subjects, value, frame, embeds, autoembed, parent, parentKey, options) +{ + // get existing embed entry + var iri = value['@id']; + var embed = (iri in embeds) ? embeds[iri] : null; + + // determine if value should be embedded or referenced, + // embed is ON if: + // 1. The frame OR default option specifies @embed as ON, AND + // 2. There is no existing embed OR it is an autoembed, AND + // autoembed mode is off. + var embedOn = ( + (('@embed' in frame && frame['@embed']) || + (!('@embed' in frame) && options.defaults.embedOn)) && + (embed === null || (embed.autoembed && !autoembed))); + + if(!embedOn) + { + // not embedding, so only use subject IRI as reference + value = {'@id': value['@id']}; + } + else + { + // create new embed entry + if(embed === null) { - // not embedding, so only use subject IRI as reference - value = {'@id': value['@id']}; + embed = {}; + embeds[iri] = embed; } - else + // replace the existing embed with a reference + else if(embed.parent !== null) { - // create new embed entry - if(embed === null) - { - embed = {}; - embeds[iri] = embed; - } - // replace the existing embed with a reference - else if(embed.parent !== null) - { - if(embed.parent[embed.key].constructor === Array) - { + if(embed.parent[embed.key].constructor === Array) + { // find and replace embed in array var objs = embed.parent[embed.key]; for(var i in objs) { - if(objs[i].constructor === Object && '@id' in objs[i] && - objs[i]['@id'] === iri) - { - objs[i] = {'@id': value['@id']}; - break; - } + if(objs[i].constructor === Object && '@id' in objs[i] && + objs[i]['@id'] === iri) + { + objs[i] = {'@id': value['@id']}; + break; + } } - } - else - { + } + else + { embed.parent[embed.key] = {'@id': value['@id']}; - } - - // recursively remove any dependent dangling embeds - var removeDependents = function(iri) - { + } + + // recursively remove any dependent dangling embeds + var removeDependents = function(iri) + { var iris = Object.keys(embeds); for(var i in iris) { - i = iris[i]; - if(i in embeds && embeds[i].parent !== null && - embeds[i].parent['@id'] === iri) - { - delete embeds[i]; - removeDependents(i); - } - } - }; - removeDependents(iri); - } - - // update embed entry - embed.autoembed = autoembed; - embed.parent = parent; - embed.key = parentKey; - - // check explicit flag - var explicitOn = ( - frame['@explicit'] === true || options.defaults.explicitOn); - if(explicitOn) - { - // remove keys from the value that aren't in the frame - for(key in value) - { + i = iris[i]; + if(i in embeds && embeds[i].parent !== null && + embeds[i].parent['@id'] === iri) + { + delete embeds[i]; + removeDependents(i); + } + } + }; + removeDependents(iri); + } + + // update embed entry + embed.autoembed = autoembed; + embed.parent = parent; + embed.key = parentKey; + + // check explicit flag + var explicitOn = ( + frame['@explicit'] === true || options.defaults.explicitOn); + if(explicitOn) + { + // remove keys from the value that aren't in the frame + for(key in value) + { // do not remove @id or any frame key if(key !== '@id' && !(key in frame)) { - delete value[key]; + delete value[key]; } - } - } - - // iterate over keys in value - var keys = Object.keys(value); - for(i in keys) - { - // skip keywords - var key = keys[i]; - if(key.indexOf('@') !== 0) - { + } + } + + // iterate over keys in value + var keys = Object.keys(value); + for(i in keys) + { + // skip keywords + var key = keys[i]; + if(key.indexOf('@') !== 0) + { // get the subframe if available if(key in frame) { - var f = frame[key]; - var _autoembed = false; + var f = frame[key]; + var _autoembed = false; } // use a catch-all subframe to preserve data from graph else { - var f = (value[key].constructor === Array) ? [] : {}; - var _autoembed = true; + var f = (value[key].constructor === Array) ? [] : {}; + var _autoembed = true; } - + // build input and do recursion var v = value[key]; var input = (v.constructor === Array) ? v : [v]; for(var n in input) { - // replace reference to subject w/embedded subject - if(input[n].constructor === Object && - '@id' in input[n] && - input[n]['@id'] in subjects) - { - input[n] = subjects[input[n]['@id']]; - } + // replace reference to subject w/embedded subject + if(input[n].constructor === Object && + '@id' in input[n] && + input[n]['@id'] in subjects) + { + input[n] = subjects[input[n]['@id']]; + } } value[key] = _frame( - subjects, input, f, embeds, _autoembed, value, key, options); - } - } - - // iterate over frame keys to add any missing values - for(key in frame) - { - // skip keywords and non-null keys in value - if(key.indexOf('@') !== 0 && (!(key in value) || value[key] === null)) - { + subjects, input, f, embeds, _autoembed, value, key, options); + } + } + + // iterate over frame keys to add any missing values + for(key in frame) + { + // skip keywords and non-null keys in value + if(key.indexOf('@') !== 0 && (!(key in value) || value[key] === null)) + { var f = frame[key]; - + // add empty array to value if(f.constructor === Array) { - value[key] = []; + value[key] = []; } // add default value to value else { - // use first subframe if frame is an array - if(f.constructor === Array) - { - f = (f.length > 0) ? f[0] : {}; - } - - // determine if omit default is on - var omitOn = ( - f['@omitDefault'] === true || options.defaults.omitDefaultOn); - if(!omitOn) - { - if('@default' in f) - { - // use specified default value - value[key] = f['@default']; - } - else - { - // built-in default value is: null - value[key] = null; - } - } + // use first subframe if frame is an array + if(f.constructor === Array) + { + f = (f.length > 0) ? f[0] : {}; + } + + // determine if omit default is on + var omitOn = ( + f['@omitDefault'] === true || options.defaults.omitDefaultOn); + if(!omitOn) + { + if('@default' in f) + { + // use specified default value + value[key] = f['@default']; + } + else + { + // built-in default value is: null + value[key] = null; + } + } } - } - } - } - - return value; - }; - - /** - * Recursively frames the given input according to the given frame. - * - * @param subjects a map of subjects in the graph. - * @param input the input to frame. - * @param frame the frame to use. - * @param embeds a map of previously embedded subjects, used to prevent cycles. - * @param autoembed true if auto-embed is on, false if not. - * @param parent the parent object (for subframing), null for none. - * @param parentKey the parent key (for subframing), null for none. - * @param options the framing options. - * - * @return the framed input. - */ - var _frame = function( - subjects, input, frame, embeds, autoembed, parent, parentKey, options) - { - var rval = null; - - // prepare output, set limit, get array of frames - var limit = -1; - var frames; - if(frame.constructor === Array) - { - rval = []; - frames = frame; - if(frames.length === 0) - { - frames.push({}); - } + } } - else + } + + return value; +}; + +/** + * Recursively frames the given input according to the given frame. + * + * @param subjects a map of subjects in the graph. + * @param input the input to frame. + * @param frame the frame to use. + * @param embeds a map of previously embedded subjects, used to prevent cycles. + * @param autoembed true if auto-embed is on, false if not. + * @param parent the parent object (for subframing), null for none. + * @param parentKey the parent key (for subframing), null for none. + * @param options the framing options. + * + * @return the framed input. + */ +var _frame = function( + subjects, input, frame, embeds, autoembed, parent, parentKey, options) +{ + var rval = null; + + // prepare output, set limit, get array of frames + var limit = -1; + var frames; + if(frame.constructor === Array) + { + rval = []; + frames = frame; + if(frames.length === 0) { - frames = [frame]; - limit = 1; + frames.push({}); } - - // iterate over frames adding input matches to list - var values = []; - for(var i = 0; i < frames.length && limit !== 0; ++i) + } + else + { + frames = [frame]; + limit = 1; + } + + // iterate over frames adding input matches to list + var values = []; + for(var i = 0; i < frames.length && limit !== 0; ++i) + { + // get next frame + frame = frames[i]; + if(frame.constructor !== Object) { - // get next frame - frame = frames[i]; - if(frame.constructor !== Object) - { - throw { + throw { message: 'Invalid JSON-LD frame. ' + - 'Frame must be an object or an array.', + 'Frame must be an object or an array.', frame: frame - }; - } - - // create array of values for each frame - values[i] = []; - for(var n = 0; n < input.length && limit !== 0; ++n) - { - // add input to list if it matches frame specific type or duck-type - var next = input[n]; - if(_isType(next, frame) || _isDuckType(next, frame)) - { + }; + } + + // create array of values for each frame + values[i] = []; + for(var n = 0; n < input.length && limit !== 0; ++n) + { + // add input to list if it matches frame specific type or duck-type + var next = input[n]; + if(_isType(next, frame) || _isDuckType(next, frame)) + { values[i].push(next); --limit; - } - } + } } - - // for each matching value, add it to the output - for(var i1 in values) + } + + // for each matching value, add it to the output + for(var i1 in values) + { + for(var i2 in values[i1]) { - for(var i2 in values[i1]) - { - frame = frames[i1]; - var value = values[i1][i2]; - - // if value is a subject, do subframing - if(_isSubject(value)) - { + frame = frames[i1]; + var value = values[i1][i2]; + + // if value is a subject, do subframing + if(_isSubject(value)) + { value = _subframe( - subjects, value, frame, embeds, autoembed, - parent, parentKey, options); - } - - // add value to output - if(rval === null) - { + subjects, value, frame, embeds, autoembed, + parent, parentKey, options); + } + + // add value to output + if(rval === null) + { rval = value; - } - else - { + } + else + { // determine if value is a reference to an embed var isRef = (_isReference(value) && value['@id'] in embeds); - + // push any value that isn't a parentless reference if(!(parent === null && isRef)) { - rval.push(value); + rval.push(value); } - } - } - } - - return rval; - }; - - /** - * Frames JSON-LD input. - * - * @param input the JSON-LD input. - * @param frame the frame to use. - * @param options framing options to use. - * - * @return the framed output. - */ - Processor.prototype.frame = function(input, frame, options) - { - var rval; - - // normalize input - input = jsonld.normalize(input); - - // save frame context - var ctx = null; - if('@context' in frame) - { - ctx = _clone(frame['@context']); - - // remove context from frame - frame = jsonld.expand(frame); + } } - else if(frame.constructor === Array) + } + + return rval; +}; + +/** + * Frames JSON-LD input. + * + * @param input the JSON-LD input. + * @param frame the frame to use. + * @param options framing options to use. + * + * @return the framed output. + */ +Processor.prototype.frame = function(input, frame, options) +{ + var rval; + + // normalize input + input = jsonld.normalize(input); + + // save frame context + var ctx = null; + if('@context' in frame) + { + ctx = _clone(frame['@context']); + + // remove context from frame + frame = jsonld.expand(frame); + } + else if(frame.constructor === Array) + { + // save first context in the array + if(frame.length > 0 && '@context' in frame[0]) { - // save first context in the array - if(frame.length > 0 && '@context' in frame[0]) - { - ctx = _clone(frame[0]['@context']); - } - - // expand all elements in the array - var tmp = []; - for(var i in frame) - { - tmp.push(jsonld.expand(frame[i])); - } - frame = tmp; + ctx = _clone(frame[0]['@context']); } - - // create framing options - // TODO: merge in options from function parameter - options = + + // expand all elements in the array + var tmp = []; + for(var i in frame) { - defaults: - { - embedOn: true, - explicitOn: false, - omitDefaultOn: false - } - }; - - // build map of all subjects - var subjects = {}; - for(var i in input) - { - subjects[input[i]['@id']] = input[i]; + tmp.push(jsonld.expand(frame[i])); } - - // frame input - rval = _frame(subjects, input, frame, {}, false, null, null, options); - - // apply context - if(ctx !== null && rval !== null) + frame = tmp; + } + + // create framing options + // TODO: merge in options from function parameter + options = + { + defaults: { - rval = jsonld.compact(ctx, rval); + embedOn: true, + explicitOn: false, + omitDefaultOn: false } + }; + + // build map of all subjects + var subjects = {}; + for(var i in input) + { + subjects[input[i]['@id']] = input[i]; + } + + // frame input + rval = _frame(subjects, input, frame, {}, false, null, null, options); + + // apply context + if(ctx !== null && rval !== null) + { + rval = jsonld.compact(ctx, rval); + } + + return rval; +}; - return rval; - }; - - })(); +})(); // exports - var JSONLDParser = {}; +var JSONLDParser = {}; - JSONLDParser.parser = {}; - JSONLDParser.parser.parse = function(data, graph) { +JSONLDParser.parser = {}; +JSONLDParser.parser.parse = function(data, graph) { if(typeof(data) === 'string') { - data = JSON.parse(data); + data = JSON.parse(data); } return jsonldParser.toTriples(data, graph); - }; +}; // end of ./src/js-communication/src/jsonld_parser.js @@ -5726,1312 +5161,1312 @@ // **N3Lexer** tokenizes N3 documents. // ## Regular expressions - var patterns = { - _explicituri: /^<((?:[^\x00-\x20<>\\"\{\}\|\^\`]|\\[uU])*)>/, - _string: /^"[^"\\]*(?:\\.[^"\\]*)*"(?=[^"\\])|^'[^'\\]*(?:\\.[^'\\]*)*'(?=[^'\\])/, - _tripleQuotedString: /^""("[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*")""|^''('[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*')''/, - _langcode: /^@([a-z]+(?:-[a-z0-9]+)*)(?=[^a-z0-9\-])/i, - _prefix: /^((?:[A-Za-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:[\.\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)?:(?=\s)/, - _qname: /^((?:[A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:[\.\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)?:((?:(?:[0-:A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~])(?:(?:[\.\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~])*(?:[\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~]))?)?)(?=[\s\.;,)#])/, - _number: /^[\-+]?(?:\d+\.?\d*([eE](?:[\-\+])?\d+)|\d+\.\d+|\.\d+|\d+)(?=\s*[\s\.;,)#])/, - _boolean: /^(?:true|false)(?=[\s#,;.])/, - _punctuation: /^\.(?!\d)|^;|^,|^\[|^\]|^\(|^\)/, // If a digit follows a dot, it is a number, not punctuation. - _fastString: /^"[^"\\]+"(?=[^"\\])/, - _keyword: /^(?:@[a-z]+|[Pp][Rr][Ee][Ff][Ii][Xx]|[Bb][Aa][Ss][Ee])(?=\s)/, - _type: /^\^\^(?:<([^>]*)>|([A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c-\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd][\-0-9A-Z_a-z\u00b7\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u037d\u037f-\u1fff\u200c-\u200d\u203f-\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]*)?:([A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c-\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd][\-0-9A-Z_a-z\u00b7\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u037d\u037f-\u1fff\u200c-\u200d\u203f-\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]*)(?=[\s\.;,)#]))/, - _shortPredicates: /^a(?=\s+|<)/, - _newline: /^[ \t]*(?:#[^\n\r]*)?(?:\r\n|\n|\r)[ \t]*/, - _whitespace: /^[ \t]+/, - _nonwhitespace: /^\S*/, - _endOfFile: /^(?:#[^\n\r]*)?$/ - }; +var patterns = { + _explicituri: /^<((?:[^\x00-\x20<>\\"\{\}\|\^\`]|\\[uU])*)>/, + _string: /^"[^"\\]*(?:\\.[^"\\]*)*"(?=[^"\\])|^'[^'\\]*(?:\\.[^'\\]*)*'(?=[^'\\])/, + _tripleQuotedString: /^""("[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*")""|^''('[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*')''/, + _langcode: /^@([a-z]+(?:-[a-z0-9]+)*)(?=[^a-z0-9\-])/i, + _prefix: /^((?:[A-Za-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:[\.\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)?:(?=\s)/, + _qname: /^((?:[A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:[\.\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)?:((?:(?:[0-:A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~])(?:(?:[\.\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~])*(?:[\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~]))?)?)(?=[\s\.;,)#])/, + _number: /^[\-+]?(?:\d+\.?\d*([eE](?:[\-\+])?\d+)|\d+\.\d+|\.\d+|\d+)(?=\s*[\s\.;,)#])/, + _boolean: /^(?:true|false)(?=[\s#,;.])/, + _punctuation: /^\.(?!\d)|^;|^,|^\[|^\]|^\(|^\)/, // If a digit follows a dot, it is a number, not punctuation. + _fastString: /^"[^"\\]+"(?=[^"\\])/, + _keyword: /^(?:@[a-z]+|[Pp][Rr][Ee][Ff][Ii][Xx]|[Bb][Aa][Ss][Ee])(?=\s)/, + _type: /^\^\^(?:<([^>]*)>|([A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c-\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd][\-0-9A-Z_a-z\u00b7\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u037d\u037f-\u1fff\u200c-\u200d\u203f-\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]*)?:([A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c-\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd][\-0-9A-Z_a-z\u00b7\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u037d\u037f-\u1fff\u200c-\u200d\u203f-\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]*)(?=[\s\.;,)#]))/, + _shortPredicates: /^a(?=\s+|<)/, + _newline: /^[ \t]*(?:#[^\n\r]*)?(?:\r\n|\n|\r)[ \t]*/, + _whitespace: /^[ \t]+/, + _nonwhitespace: /^\S*/, + _endOfFile: /^(?:#[^\n\r]*)?$/ +}; // Regular expression and replacement string to escape N3 strings. // Note how we catch invalid unicode sequences separately (they will trigger an error). - var escapeSequence = /\\u([a-fA-F0-9]{4})|\\U([a-fA-F0-9]{8})|\\[uU]|\\(.)/g; - var escapeReplacements = { '\\': '\\', "'": "'", '"': '"', - 'n': '\n', 'r': '\r', 't': '\t', 'f': '\f', 'b': '\b', - '_': '_', '~': '~', '.': '.', '-': '-', '!': '!', '$': '$', '&': '&', - '(': '(', ')': ')', '*': '*', '+': '+', ',': ',', ';': ';', '=': '=', - '/': '/', '?': '?', '#': '#', '@': '@', '%': '%' }; - var illegalUrlChars = /[\x00-\x20<>\\"\{\}\|\^\`]/; +var escapeSequence = /\\u([a-fA-F0-9]{4})|\\U([a-fA-F0-9]{8})|\\[uU]|\\(.)/g; +var escapeReplacements = { '\\': '\\', "'": "'", '"': '"', + 'n': '\n', 'r': '\r', 't': '\t', 'f': '\f', 'b': '\b', + '_': '_', '~': '~', '.': '.', '-': '-', '!': '!', '$': '$', '&': '&', + '(': '(', ')': ')', '*': '*', '+': '+', ',': ',', ';': ';', '=': '=', + '/': '/', '?': '?', '#': '#', '@': '@', '%': '%' }; +var illegalUrlChars = /[\x00-\x20<>\\"\{\}\|\^\`]/; // Different punctuation types. - var punctuationTypes = { '.': 'dot', ';': 'semicolon', ',': 'comma', - '[': 'bracketopen', ']': 'bracketclose', - '(': 'liststart', ')': 'listend' }; - var fullPredicates = { 'a': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' }; +var punctuationTypes = { '.': 'dot', ';': 'semicolon', ',': 'comma', + '[': 'bracketopen', ']': 'bracketclose', + '(': 'liststart', ')': 'listend' }; +var fullPredicates = { 'a': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' }; // ## Constructor - function N3Lexer() { - if (!(this instanceof N3Lexer)) - return new N3Lexer(); - - // Local copies of the patterns perform slightly better. - for (var name in patterns) - this[name] = patterns[name]; - } - - N3Lexer.prototype = { - // ## Private methods +function N3Lexer() { + if (!(this instanceof N3Lexer)) + return new N3Lexer(); + + // Local copies of the patterns perform slightly better. + for (var name in patterns) + this[name] = patterns[name]; +} + +N3Lexer.prototype = { + // ## Private methods + + // ### `_next` fires the callback with the next token. + // Returns a boolean indicating whether a token has been emitted. + _next: function (callback) { + // Only emit tokens if there's still input left. + if (this._input === undefined) + return false; - // ### `_next` fires the callback with the next token. - // Returns a boolean indicating whether a token has been emitted. - _next: function (callback) { - // Only emit tokens if there's still input left. - if (this._input === undefined) - return false; + // Count and skip newlines. + var match; + while (match = this._newline.exec(this._input)) { + this._line++; + this._input = this._input.substr(match[0].length); + } - // Count and skip newlines. - var match; - while (match = this._newline.exec(this._input)) { - this._line++; - this._input = this._input.substr(match[0].length); - } + // Skip whitespace. + if (match = this._whitespace.exec(this._input)) { + this._input = this._input.substr(match[0].length); + } - // Skip whitespace. - if (match = this._whitespace.exec(this._input)) { - this._input = this._input.substr(match[0].length); - } + // Create token skeleton. + // We initialize all possible properties as strings, so the engine uses one runtime type for all tokens. + var token = { line: this._line, + type: '', + value: '', + prefix: '' + }; + var unescaped; - // Create token skeleton. - // We initialize all possible properties as strings, so the engine uses one runtime type for all tokens. - var token = { line: this._line, - type: '', - value: '', - prefix: '' - }; - var unescaped; - - // Emit the EOF token if we're at the end and reading is complete. - if (this._endOfFile.test(this._input)) { - // If we're streaming, don't emit EOF yet. - if (!this._inputComplete) - return false; - // Free the input. - delete this._input; - // Emit EOF. - token.type = 'eof'; - callback(null, token); - return true; - } + // Emit the EOF token if we're at the end and reading is complete. + if (this._endOfFile.test(this._input)) { + // If we're streaming, don't emit EOF yet. + if (!this._inputComplete) + return false; + // Free the input. + delete this._input; + // Emit EOF. + token.type = 'eof'; + callback(null, token); + return true; + } - // Try to find an `explicituri`. - if (match = this._explicituri.exec(this._input)) { - unescaped = this._unescape(match[1]); - if (unescaped === null || illegalUrlChars.test(unescaped)) - return reportSyntaxError(this); - token.type = 'explicituri'; - token.value = unescaped; - } - // Try to find a dot. - else if (match = this._punctuation.exec(this._input)) { - token.type = punctuationTypes[match[0]]; - } - // Try to find a language code. - else if (this._prevTokenType === 'literal' && (match = this._langcode.exec(this._input))) { - token.type = 'langcode'; + // Try to find an `explicituri`. + if (match = this._explicituri.exec(this._input)) { + unescaped = this._unescape(match[1]); + if (unescaped === null || illegalUrlChars.test(unescaped)) + return reportSyntaxError(this); + token.type = 'explicituri'; + token.value = unescaped; + } + // Try to find a dot. + else if (match = this._punctuation.exec(this._input)) { + token.type = punctuationTypes[match[0]]; + } + // Try to find a language code. + else if (this._prevTokenType === 'literal' && (match = this._langcode.exec(this._input))) { + token.type = 'langcode'; + token.value = match[1]; + } + // Try to find a string literal the fast way. + // This only includes non-empty simple quoted literals without escapes. + // If streaming, make sure the input is long enough so we don't miss language codes or string types. + else if (match = this._fastString.exec(this._input)) { + token.type = 'literal'; + token.value = match[0]; + } + // Try to find any other string literal wrapped in a pair of quotes. + else if (match = this._string.exec(this._input)) { + unescaped = this._unescape(match[0]); + if (unescaped === null) + return reportSyntaxError(this); + token.type = 'literal'; + token.value = unescaped.replace(/^'|'$/g, '"'); + } + // Try to find a string literal wrapped in a pair of triple quotes. + else if (match = this._tripleQuotedString.exec(this._input)) { + unescaped = match[1] || match[2]; + // Count the newlines and advance line counter. + this._line += unescaped.split(/\r\n|\r|\n/).length - 1; + unescaped = this._unescape(unescaped); + if (unescaped === null) + return reportSyntaxError(this); + token.type = 'literal'; + token.value = unescaped.replace(/^'|'$/g, '"'); + } + // Try to find a number. + else if (match = this._number.exec(this._input)) { + token.type = 'literal'; + token.value = '"' + match[0] + '"^^' : (/^[+\-]?\d+$/.test(match[0]) ? 'integer>' : 'decimal>')); + } + // Try to match a boolean. + else if (match = this._boolean.exec(this._input)) { + token.type = 'literal'; + token.value = '"' + match[0] + '"^^'; + } + // Try to find a type. + else if (this._prevTokenType === 'literal' && (match = this._type.exec(this._input))) { + token.type = 'type'; + if (!match[2]) { token.value = match[1]; } - // Try to find a string literal the fast way. - // This only includes non-empty simple quoted literals without escapes. - // If streaming, make sure the input is long enough so we don't miss language codes or string types. - else if (match = this._fastString.exec(this._input)) { - token.type = 'literal'; - token.value = match[0]; - } - // Try to find any other string literal wrapped in a pair of quotes. - else if (match = this._string.exec(this._input)) { - unescaped = this._unescape(match[0]); - if (unescaped === null) - return reportSyntaxError(this); - token.type = 'literal'; - token.value = unescaped.replace(/^'|'$/g, '"'); - } - // Try to find a string literal wrapped in a pair of triple quotes. - else if (match = this._tripleQuotedString.exec(this._input)) { - unescaped = match[1] || match[2]; - // Count the newlines and advance line counter. - this._line += unescaped.split(/\r\n|\r|\n/).length - 1; - unescaped = this._unescape(unescaped); - if (unescaped === null) - return reportSyntaxError(this); - token.type = 'literal'; - token.value = unescaped.replace(/^'|'$/g, '"'); - } - // Try to find a number. - else if (match = this._number.exec(this._input)) { - token.type = 'literal'; - token.value = '"' + match[0] + '"^^' : (/^[+\-]?\d+$/.test(match[0]) ? 'integer>' : 'decimal>')); - } - // Try to match a boolean. - else if (match = this._boolean.exec(this._input)) { - token.type = 'literal'; - token.value = '"' + match[0] + '"^^'; - } - // Try to find a type. - else if (this._prevTokenType === 'literal' && (match = this._type.exec(this._input))) { - token.type = 'type'; - if (!match[2]) { - token.value = match[1]; - } - else { - token.prefix = match[2]; - token.value = match[3]; - } - } - // Try to find a keyword. - else if (match = this._keyword.exec(this._input)) { - var keyword = match[0]; - token.type = keyword[0] === '@' ? keyword : keyword.toUpperCase(); - } - // Try to find a prefix. - else if ((this._prevTokenType === '@prefix' || this._prevTokenType === 'PREFIX') && - (match = this._prefix.exec(this._input))) { - token.type = 'prefix'; - token.value = match[1] || ''; - } - // Try to find a qname. - else if (match = this._qname.exec(this._input)) { - unescaped = this._unescape(match[2]); - if (unescaped === null) - return reportSyntaxError(this); - token.type = 'qname'; - token.prefix = match[1] || ''; - token.value = unescaped; - } - // Try to find an abbreviated predicate. - else if (match = this._shortPredicates.exec(this._input)) { - token.type = 'abbreviation'; - token.value = fullPredicates[match[0]]; - } - // What if nothing of the above was found? else { - // We could be in streaming mode, and then we just wait for more input to arrive. - // Otherwise, a syntax error has occurred in the input. - // One exception: error on an unaccounted linebreak (= not inside a triple-quoted literal). - if (this._inputComplete || (!/^'''|^"""/.test(this._input) && /\n|\r/.test(this._input))) - reportSyntaxError(this); - return false; - } + token.prefix = match[2]; + token.value = match[3]; + } + } + // Try to find a keyword. + else if (match = this._keyword.exec(this._input)) { + var keyword = match[0]; + token.type = keyword[0] === '@' ? keyword : keyword.toUpperCase(); + } + // Try to find a prefix. + else if ((this._prevTokenType === '@prefix' || this._prevTokenType === 'PREFIX') && + (match = this._prefix.exec(this._input))) { + token.type = 'prefix'; + token.value = match[1] || ''; + } + // Try to find a qname. + else if (match = this._qname.exec(this._input)) { + unescaped = this._unescape(match[2]); + if (unescaped === null) + return reportSyntaxError(this); + token.type = 'qname'; + token.prefix = match[1] || ''; + token.value = unescaped; + } + // Try to find an abbreviated predicate. + else if (match = this._shortPredicates.exec(this._input)) { + token.type = 'abbreviation'; + token.value = fullPredicates[match[0]]; + } + // What if nothing of the above was found? + else { + // We could be in streaming mode, and then we just wait for more input to arrive. + // Otherwise, a syntax error has occurred in the input. + // One exception: error on an unaccounted linebreak (= not inside a triple-quoted literal). + if (this._inputComplete || (!/^'''|^"""/.test(this._input) && /\n|\r/.test(this._input))) + reportSyntaxError(this); + return false; + } - // Save the token type for the next iteration. - this._prevTokenType = token.type; + // Save the token type for the next iteration. + this._prevTokenType = token.type; - // Advance to next part to tokenize. - this._input = this._input.substr(match[0].length); + // Advance to next part to tokenize. + this._input = this._input.substr(match[0].length); - // Emit the parsed token. - callback(null, token); - return true; + // Emit the parsed token. + callback(null, token); + return true; - function reportSyntaxError(self) { - match = self._nonwhitespace.exec(self._input); - delete self._input; - callback('Syntax error: unexpected "' + match[0] + '" on line ' + self._line + '.'); - return false; - } - }, + function reportSyntaxError(self) { + match = self._nonwhitespace.exec(self._input); + delete self._input; + callback('Syntax error: unexpected "' + match[0] + '" on line ' + self._line + '.'); + return false; + } + }, - // ### `unescape` replaces N3 escape codes by their corresponding characters. - _unescape: function (item) { - try { - return item.replace(escapeSequence, function (sequence, unicode4, unicode8, escapedChar) { - var charCode; - if (unicode4) { - charCode = parseInt(unicode4, 16); - if (isNaN(charCode)) - throw "invalid character code"; + // ### `unescape` replaces N3 escape codes by their corresponding characters. + _unescape: function (item) { + try { + return item.replace(escapeSequence, function (sequence, unicode4, unicode8, escapedChar) { + var charCode; + if (unicode4) { + charCode = parseInt(unicode4, 16); + if (isNaN(charCode)) + throw "invalid character code"; + return String.fromCharCode(charCode); + } + else if (unicode8) { + charCode = parseInt(unicode8, 16); + if (isNaN(charCode)) + throw "invalid character code"; + if (charCode < 0xFFFF) return String.fromCharCode(charCode); - } - else if (unicode8) { - charCode = parseInt(unicode8, 16); - if (isNaN(charCode)) - throw "invalid character code"; - if (charCode < 0xFFFF) - return String.fromCharCode(charCode); - return String.fromCharCode(Math.floor((charCode - 0x10000) / 0x400) + 0xD800) + - String.fromCharCode((charCode - 0x10000) % 0x400 + 0xDC00); - } - else { - var replacement = escapeReplacements[escapedChar]; - if (!replacement) - throw "invalid escape sequence"; - return replacement; - } - }); - } - catch (error) { - return null; - } - }, - - // ## Public methods - - // ### `tokenize` starts the transformation of an N3 document into an array of tokens. - // The input can be a string or a stream. - tokenize: function (input, callback) { - var self = this; - this._line = 1; - - // If the input is a string, continuously emit tokens through callback until the end. - if (typeof(input) === 'string') { - this._input = input; - this._inputComplete = true; - process.nextTick(function () { - while (self._next(callback)) {} ; - }); - } - // Otherwise, the input must be a stream. - else { - this._input = ''; - this._inputComplete = false; - - // Read strings, not buffers. - if (typeof input.setEncoding === 'function') - input.setEncoding('utf8'); - - // If new data arrives… - input.on('data', function (data) { - // …add the new data to the buffer - self._input += data; - // …and parse as far as we can. - while (self._next(callback)) {} ; - }); - // If we're at the end of the stream… - input.on('end', function () { - // …signal completeness… - self._inputComplete = true; - // …and parse until the end. - while (self._next(callback)) {} ; - }); - } + return String.fromCharCode(Math.floor((charCode - 0x10000) / 0x400) + 0xD800) + + String.fromCharCode((charCode - 0x10000) % 0x400 + 0xDC00); + } + else { + var replacement = escapeReplacements[escapedChar]; + if (!replacement) + throw "invalid escape sequence"; + return replacement; + } + }); } - }; + catch (error) { + return null; + } + }, + + // ## Public methods + + // ### `tokenize` starts the transformation of an N3 document into an array of tokens. + // The input can be a string or a stream. + tokenize: function (input, callback) { + var self = this; + this._line = 1; + + // If the input is a string, continuously emit tokens through callback until the end. + if (typeof(input) === 'string') { + this._input = input; + this._inputComplete = true; + process.nextTick(function () { + while (self._next(callback)) {} ; + }); + } + // Otherwise, the input must be a stream. + else { + this._input = ''; + this._inputComplete = false; + + // Read strings, not buffers. + if (typeof input.setEncoding === 'function') + input.setEncoding('utf8'); + + // If new data arrives… + input.on('data', function (data) { + // …add the new data to the buffer + self._input += data; + // …and parse as far as we can. + while (self._next(callback)) {} ; + }); + // If we're at the end of the stream… + input.on('end', function () { + // …signal completeness… + self._inputComplete = true; + // …and parse until the end. + while (self._next(callback)) {} ; + }); + } + } +}; // ## Exports // **RVInnerN3Parser** parses N3 documents. - var RDF_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', +var RDF_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', RDF_NIL = {token: 'uri', value: RDF_PREFIX + 'nil', prefix: null, suffix: null}, RDF_FIRST = {token: 'uri', value: RDF_PREFIX + 'first', prefix: null, suffix: null}, RDF_REST = {token: 'uri', value: RDF_PREFIX + 'rest', prefix: null, suffix: null}; - var absoluteURI = /^[a-z]+:/, +var absoluteURI = /^[a-z]+:/, absolutePath = /^\//, hashURI = /^#/, documentPart = /[^\/]*$/, rootURI = /^(?:[a-z]+:\/*)?[^\/]*/; - var _undefined, noop = function () {}; +var _undefined, noop = function () {}; // ## Constructor - function RVInnerN3Parser(config) { - if (!(this instanceof RVInnerN3Parser)) - return new RVInnerN3Parser(config); - - config = config || {}; - - this._lexer = config.lexer || new N3Lexer(); - this._blankNodes = Object.create(null); - this._blankNodeCount = 0; - this._tripleStack = []; - if(config.baseURI != null) - config.documentURI = config.baseURI - if (!config.documentURI) { - this._baseURI = null; - this._baseURIPath = null; - } - else { - if(config.documentURI.indexOf("#") !== -1) +function RVInnerN3Parser(config) { + if (!(this instanceof RVInnerN3Parser)) + return new RVInnerN3Parser(config); + + config = config || {}; + + this._lexer = config.lexer || new N3Lexer(); + this._blankNodes = Object.create(null); + this._blankNodeCount = 0; + this._tripleStack = []; + if(config.baseURI != null) + config.documentURI = config.baseURI + if (!config.documentURI) { + this._baseURI = null; + this._baseURIPath = null; + } + else { + if(config.documentURI.indexOf("#") !== -1) config.documentURI = config.documentURI.split("#")[0]; - this._baseURI = config.documentURI; - this._baseURIPath = this._baseURI.replace(documentPart, ''); - this._baseURIRoot = this._baseURI.match(rootURI)[0]; - } + this._baseURI = config.documentURI; + this._baseURIPath = this._baseURI.replace(documentPart, ''); + this._baseURIRoot = this._baseURI.match(rootURI)[0]; } +} + +RVInnerN3Parser.prototype = { + defaultGraph: null, + constructor: RVInnerN3Parser, + + // ## Private methods + + // ### `_readInTopContext` reads a token when in the top context. + _readInTopContext: function (token) { + switch (token.type) { + // If an EOF token arrives in the top context, signal that we're done. + case 'eof': + return this._callback(null, null, this._prefixes); + // It could be a prefix declaration. + case '@prefix': + this._sparqlStyle = false; + return this._readPrefix; + case 'PREFIX': + this._sparqlStyle = true; + return this._readPrefix; + // It could be a base declaration. + case '@base': + this._sparqlStyle = false; + return this._readBaseURI; + case 'BASE': + this._sparqlStyle = true; + return this._readBaseURI; + // Otherwise, the next token must be a subject. + default: + return this._readSubject(token); + } + }, + + // ### `_readSubject` reads a triple's subject. + _readSubject: function (token) { + switch (token.type) { + case 'explicituri': + if (this._baseURI === null || absoluteURI.test(token.value)) + this._subject = {token: 'uri', value: token.value, prefix: null, suffix: null}; + else - RVInnerN3Parser.prototype = { - defaultGraph: null, - constructor: RVInnerN3Parser, - - // ## Private methods - - // ### `_readInTopContext` reads a token when in the top context. - _readInTopContext: function (token) { - switch (token.type) { - // If an EOF token arrives in the top context, signal that we're done. - case 'eof': - return this._callback(null, null, this._prefixes); - // It could be a prefix declaration. - case '@prefix': - this._sparqlStyle = false; - return this._readPrefix; - case 'PREFIX': - this._sparqlStyle = true; - return this._readPrefix; - // It could be a base declaration. - case '@base': - this._sparqlStyle = false; - return this._readBaseURI; - case 'BASE': - this._sparqlStyle = true; - return this._readBaseURI; - // Otherwise, the next token must be a subject. - default: - return this._readSubject(token); - } - }, - - // ### `_readSubject` reads a triple's subject. - _readSubject: function (token) { - switch (token.type) { - case 'explicituri': - if (this._baseURI === null || absoluteURI.test(token.value)) - this._subject = {token: 'uri', value: token.value, prefix: null, suffix: null}; - else - - this._subject = {token: 'uri', value: this._resolveURI(token.value), prefix: null, suffix: null}; - break; - case 'qname': - if (token.prefix === '_') { - if(this._blankNodes[token.value] !== undefined) { + this._subject = {token: 'uri', value: this._resolveURI(token.value), prefix: null, suffix: null}; + break; + case 'qname': + if (token.prefix === '_') { + if(this._blankNodes[token.value] !== undefined) { this._subject = {'blank': this._blankNodes[token.value] }; - } else { + } else { this._subject = {'blank': (this._blankNodes[token.value] = '_:' + this._blankNodeCount++)}; - } - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === _undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._subject = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; - } - break; - case 'bracketopen': - // Start a new triple with a new blank node as subject. - this._subject = {'blank': ('_:' + this._blankNodeCount++)}; - this._tripleStack.push({ subject: this._subject, predicate: null, object: null, type: 'blank' }); - return this._readBlankNodeHead; - case 'liststart': - // Start a new list - this._tripleStack.push({ subject: RDF_NIL, predicate: null, object: null, type: 'list' }); - this._subject = null; - return this._readListItem; - default: - return this._error('Unexpected token type "' + token.type, token); } - this._subjectHasPredicate = false; - // The next token must be a predicate. - return this._readPredicate; - }, - - // ### `_readPredicate` reads a triple's predicate. - _readPredicate: function (token) { - switch (token.type) { - case 'explicituri': - case 'abbreviation': - if (this._baseURI === null || absoluteURI.test(token.value)) - this._predicate = {token: 'uri', value: token.value, prefix: null, suffix: null}; - else { - var resolved = - this._predicate = {token: 'uri', value: this._resolveURI(token.value), prefix: null, suffix: null}; - } - break; - case 'qname': - if (token.prefix === '_') { - return this._error('Disallowed blank node as predicate', token); - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === _undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._predicate = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; - } - break; - case 'bracketclose': - // Expected predicate didn't come, must have been trailing semicolon. - return this._readBlankNodeTail(token, true); - case 'dot': - // A dot is not allowed if the subject did not have a predicate yet - if (!this._subjectHasPredicate) - return this._error('Unexpected dot', token); - // Expected predicate didn't come, must have been trailing semicolon. - return this._readPunctuation(token, true); - case 'semicolon': - // Extra semicolons can be safely ignored - return this._readPredicate; - default: - return this._error('Expected predicate to follow "' + this._subject + '"', token); + else { + var prefix = this._prefixes[token.prefix]; + if (prefix === _undefined) + return this._error('Undefined prefix "' + token.prefix + ':"', token); + this._subject = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; + + } + break; + case 'bracketopen': + // Start a new triple with a new blank node as subject. + this._subject = {'blank': ('_:' + this._blankNodeCount++)}; + this._tripleStack.push({ subject: this._subject, predicate: null, object: null, type: 'blank' }); + return this._readBlankNodeHead; + case 'liststart': + // Start a new list + this._tripleStack.push({ subject: RDF_NIL, predicate: null, object: null, type: 'list' }); + this._subject = null; + return this._readListItem; + default: + return this._error('Unexpected token type "' + token.type, token); + } + this._subjectHasPredicate = false; + // The next token must be a predicate. + return this._readPredicate; + }, + + // ### `_readPredicate` reads a triple's predicate. + _readPredicate: function (token) { + switch (token.type) { + case 'explicituri': + case 'abbreviation': + if (this._baseURI === null || absoluteURI.test(token.value)) + this._predicate = {token: 'uri', value: token.value, prefix: null, suffix: null}; + else { + var resolved = + this._predicate = {token: 'uri', value: this._resolveURI(token.value), prefix: null, suffix: null}; } - this._subjectHasPredicate = true; - // The next token must be an object. - return this._readObject; - }, - - // ### `_readObject` reads a triple's object. - _readObject: function (token) { - switch (token.type) { - case 'explicituri': - if (this._baseURI === null || absoluteURI.test(token.value)) - this._object = {token: 'uri', value: token.value, prefix: null, suffix: null}; - else - this._object = {token: 'uri', value: this._resolveURI(token.value), prefix: null, suffix: null}; - break; - case 'qname': - if (token.prefix === '_') { - if(this._blankNodes[token.value] !== undefined) { + break; + case 'qname': + if (token.prefix === '_') { + return this._error('Disallowed blank node as predicate', token); + } + else { + var prefix = this._prefixes[token.prefix]; + if (prefix === _undefined) + return this._error('Undefined prefix "' + token.prefix + ':"', token); + this._predicate = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; + } + break; + case 'bracketclose': + // Expected predicate didn't come, must have been trailing semicolon. + return this._readBlankNodeTail(token, true); + case 'dot': + // A dot is not allowed if the subject did not have a predicate yet + if (!this._subjectHasPredicate) + return this._error('Unexpected dot', token); + // Expected predicate didn't come, must have been trailing semicolon. + return this._readPunctuation(token, true); + case 'semicolon': + // Extra semicolons can be safely ignored + return this._readPredicate; + default: + return this._error('Expected predicate to follow "' + this._subject + '"', token); + } + this._subjectHasPredicate = true; + // The next token must be an object. + return this._readObject; + }, + + // ### `_readObject` reads a triple's object. + _readObject: function (token) { + switch (token.type) { + case 'explicituri': + if (this._baseURI === null || absoluteURI.test(token.value)) + this._object = {token: 'uri', value: token.value, prefix: null, suffix: null}; + else + this._object = {token: 'uri', value: this._resolveURI(token.value), prefix: null, suffix: null}; + break; + case 'qname': + if (token.prefix === '_') { + if(this._blankNodes[token.value] !== undefined) { this._object = {'blank': this._blankNodes[token.value] }; - } else { + } else { this._object = {'blank': (this._blankNodes[token.value] = '_:' + this._blankNodeCount++)}; - } - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === _undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._object = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; } - break; - case 'literal': - this._object = {'literal': token.value}; - return this._readDataTypeOrLang; - case 'bracketopen': - // Start a new triple with a new blank node as subject. - var blank = {'blank': ('_:' + this._blankNodeCount++)}; - this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: blank, type: 'blank' }); - this._subject = blank; - return this._readBlankNodeHead; - case 'liststart': - // Start a new list - this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: RDF_NIL, type: 'list' }); - this._subject = null; - return this._readListItem; - default: - return this._error('Expected object to follow "' + this._predicate + '"', token); } + else { + var prefix = this._prefixes[token.prefix]; + if (prefix === _undefined) + return this._error('Undefined prefix "' + token.prefix + ':"', token); + this._object = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; + } + break; + case 'literal': + this._object = {'literal': token.value}; + return this._readDataTypeOrLang; + case 'bracketopen': + // Start a new triple with a new blank node as subject. + var blank = {'blank': ('_:' + this._blankNodeCount++)}; + this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: blank, type: 'blank' }); + this._subject = blank; + return this._readBlankNodeHead; + case 'liststart': + // Start a new list + this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: RDF_NIL, type: 'list' }); + this._subject = null; + return this._readListItem; + default: + return this._error('Expected object to follow "' + this._predicate + '"', token); + } + return this._getTripleEndReader(); + }, + + // ### `_readBlankNodeHead` reads the head of a blank node. + _readBlankNodeHead: function (token) { + if (token.type === 'bracketclose') + return this._readBlankNodeTail(token, true); + else + return this._readPredicate(token); + }, + + // ### `_readBlankNodeTail` reads the end of a blank node. + _readBlankNodeTail: function (token, empty) { + if (token.type !== 'bracketclose') + return this._readPunctuation(token); + + // Store blank node triple. + if (empty !== true) + this._callback(null, { subject: this._subject, + predicate: this._predicate, + object: this._object, + graph: RVInnerN3Parser.prototype.defaultGraph }); + + // Restore parent triple that contains the blank node. + var triple = this._tripleStack.pop(); + this._subject = triple.subject; + // Was the blank node the object? + if (triple.object !== null) { + // Restore predicate and object as well, and continue by reading punctuation. + this._predicate = triple.predicate; + this._object = triple.object; return this._getTripleEndReader(); - }, - - // ### `_readBlankNodeHead` reads the head of a blank node. - _readBlankNodeHead: function (token) { - if (token.type === 'bracketclose') - return this._readBlankNodeTail(token, true); - else - return this._readPredicate(token); - }, - - // ### `_readBlankNodeTail` reads the end of a blank node. - _readBlankNodeTail: function (token, empty) { - if (token.type !== 'bracketclose') - return this._readPunctuation(token); - - // Store blank node triple. - if (empty !== true) - this._callback(null, { subject: this._subject, - predicate: this._predicate, - object: this._object, - graph: RVInnerN3Parser.prototype.defaultGraph }); - - // Restore parent triple that contains the blank node. - var triple = this._tripleStack.pop(); - this._subject = triple.subject; - // Was the blank node the object? - if (triple.object !== null) { - // Restore predicate and object as well, and continue by reading punctuation. - this._predicate = triple.predicate; - this._object = triple.object; - return this._getTripleEndReader(); - } - // The blank node was the subject, so continue reading the predicate. - return this._readPredicate; - }, + } + // The blank node was the subject, so continue reading the predicate. + return this._readPredicate; + }, - // ### `_readDataTypeOrLang` reads an _optional_ data type or language. - _readDataTypeOrLang: function (token) { - switch (token.type) { - case 'type': - var value; - if (token.prefix === '') { - value = token.value; - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === _undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - value = prefix + token.value; - } - if(this._object.literal) { - this._object.literal += '^^<' + value + '>'; - } else { - this._object += '^^<' + value + '>'; - this._object = {literal: this._object}; - } + // ### `_readDataTypeOrLang` reads an _optional_ data type or language. + _readDataTypeOrLang: function (token) { + switch (token.type) { + case 'type': + var value; + if (token.prefix === '') { + value = token.value; + } + else { + var prefix = this._prefixes[token.prefix]; + if (prefix === _undefined) + return this._error('Undefined prefix "' + token.prefix + ':"', token); + value = prefix + token.value; + } + if(this._object.literal) { + this._object.literal += '^^<' + value + '>'; + } else { + this._object += '^^<' + value + '>'; + this._object = {literal: this._object}; + } - return this._getTripleEndReader(); - case 'langcode': - if(this._object.literal) { + return this._getTripleEndReader(); + case 'langcode': + if(this._object.literal) { this._object.literal += '@' + token.value.toLowerCase(); - } else { + } else { this._object += '@' + token.value.toLowerCase(); this._object = {literal: this._object}; - } - return this._getTripleEndReader(); - default: - return this._getTripleEndReader().call(this, token); - } - }, + } + return this._getTripleEndReader(); + default: + return this._getTripleEndReader().call(this, token); + } + }, - // ### `_readListItem` reads items from a list. - _readListItem: function (token) { - var item = null, // The actual list item. + // ### `_readListItem` reads items from a list. + _readListItem: function (token) { + var item = null, // The actual list item. itemHead = null, // The head of the rdf:first predicate. prevItemHead = this._subject, // The head of the previous rdf:first predicate. stack = this._tripleStack, // The stack of triples part of recursion (lists, blanks, etc.). parentTriple = stack[stack.length - 1], // The triple containing the current list. next = this._readListItem; // The next function to execute. - switch (token.type) { - case 'explicituri': - item = {'token': 'uri', 'value': token.value, 'prefix': null, 'suffix': null}; - break; - case 'qname': - if (token.prefix === '_') { - if(this._blankNodes[token.value] !== undefined) { + switch (token.type) { + case 'explicituri': + item = {'token': 'uri', 'value': token.value, 'prefix': null, 'suffix': null}; + break; + case 'qname': + if (token.prefix === '_') { + if(this._blankNodes[token.value] !== undefined) { item = {'blank': this._blankNodes[token.value] }; - } else { + } else { tiem = {'blank': (this._blankNodes[token.value] = '_:' + this._blankNodeCount++)}; - } } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === _undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - item = {'token': 'uri', 'value': prefix + token.value, 'prefix': null, 'suffix': null}; - } - break; - case 'literal': - item = {'literal': token.value }; - next = this._readDataTypeOrLang; - break; - case 'bracketopen': - // Stack the current list triple and start a new triple with a blank node as subject. - itemHead = {'blank': '_:' + this._blankNodeCount++ }; - item = {'blank': '_:' + this._blankNodeCount++ }; - - stack.push({ subject: itemHead, predicate: RDF_FIRST, object: item, type: 'blank' }); - this._subject = item; - next = this._readBlankNodeHead; - break; - case 'liststart': - // Stack the current list triple and start a new list - itemHead = {'blank': '_:' + this._blankNodeCount++}; - stack.push({ subject: itemHead, predicate: RDF_FIRST, object: RDF_NIL, type: 'list' }); - this._subject = null; - next = this._readListItem; - break; - case 'listend': - // Restore the parent triple. - stack.pop(); - // If this list is contained within a parent list, return the membership triple here. - // This will be `t rdf:first .`. - if (stack.length !== 0 && stack[stack.length - 1].type === 'list') - this._callback(null, { subject: parentTriple.subject, - predicate: parentTriple.predicate, - object: parentTriple.object, - graph: RVInnerN3Parser.prototype.defaultGraph }); - // Restore the parent triple's subject. - this._subject = (typeof(parentTriple.subject) === 'string' ? {'token': 'uri', 'value': parentTriple.subject, 'prefix': null, 'suffix': null } : parentTriple.subject); - // Was this list in the parent triple's subject? - if (parentTriple.predicate === null) { - // The next token is the predicate. - next = this._readPredicate; - // Skip writing the list tail if this was an empty list. - if (parentTriple.subject === RDF_NIL) - return next; - } - // The list was in the parent triple's object. - else { - // Restore the parent triple's predicate and object as well. - this._predicate = (typeof(parentTriple.predicate) === 'string' ? {'token': 'uri', 'value': parentTriple.predicate, 'prefix': null, 'suffix': null } : parentTriple.predicate); - this._object = (typeof(parentTriple.object) === 'string' ? {'token': 'uri', 'value': parentTriple.object, 'prefix': null, 'suffix': null } : parentTriple.object); - - next = this._getTripleEndReader(); - // Skip writing the list tail if this was an empty list. - if (parentTriple.object === RDF_NIL) - return next; - } - // Close the list by making the item head nil. - itemHead = RDF_NIL; - break; - default: - return this._error('Expected list item instead of "' + token.type + '"', token); } + else { + var prefix = this._prefixes[token.prefix]; + if (prefix === _undefined) + return this._error('Undefined prefix "' + token.prefix + ':"', token); + item = {'token': 'uri', 'value': prefix + token.value, 'prefix': null, 'suffix': null}; + } + break; + case 'literal': + item = {'literal': token.value }; + next = this._readDataTypeOrLang; + break; + case 'bracketopen': + // Stack the current list triple and start a new triple with a blank node as subject. + itemHead = {'blank': '_:' + this._blankNodeCount++ }; + item = {'blank': '_:' + this._blankNodeCount++ }; + + stack.push({ subject: itemHead, predicate: RDF_FIRST, object: item, type: 'blank' }); + this._subject = item; + next = this._readBlankNodeHead; + break; + case 'liststart': + // Stack the current list triple and start a new list + itemHead = {'blank': '_:' + this._blankNodeCount++}; + stack.push({ subject: itemHead, predicate: RDF_FIRST, object: RDF_NIL, type: 'list' }); + this._subject = null; + next = this._readListItem; + break; + case 'listend': + // Restore the parent triple. + stack.pop(); + // If this list is contained within a parent list, return the membership triple here. + // This will be `t rdf:first .`. + if (stack.length !== 0 && stack[stack.length - 1].type === 'list') + this._callback(null, { subject: parentTriple.subject, + predicate: parentTriple.predicate, + object: parentTriple.object, + graph: RVInnerN3Parser.prototype.defaultGraph }); + // Restore the parent triple's subject. + this._subject = (typeof(parentTriple.subject) === 'string' ? {'token': 'uri', 'value': parentTriple.subject, 'prefix': null, 'suffix': null } : parentTriple.subject); + // Was this list in the parent triple's subject? + if (parentTriple.predicate === null) { + // The next token is the predicate. + next = this._readPredicate; + // Skip writing the list tail if this was an empty list. + if (parentTriple.subject === RDF_NIL) + return next; + } + // The list was in the parent triple's object. + else { + // Restore the parent triple's predicate and object as well. + this._predicate = (typeof(parentTriple.predicate) === 'string' ? {'token': 'uri', 'value': parentTriple.predicate, 'prefix': null, 'suffix': null } : parentTriple.predicate); + this._object = (typeof(parentTriple.object) === 'string' ? {'token': 'uri', 'value': parentTriple.object, 'prefix': null, 'suffix': null } : parentTriple.object); - // Create a new blank node if no item head was assigned yet. - if (itemHead === null) - this._subject = itemHead = {'blank': '_:' + this._blankNodeCount++}; - - // Is this the first element of the list? - if (prevItemHead === null) { - // This list is either the object or the subject. + next = this._getTripleEndReader(); + // Skip writing the list tail if this was an empty list. if (parentTriple.object === RDF_NIL) - parentTriple.object = itemHead; - else - parentTriple.subject = itemHead; + return next; } - else { - // The rest of the list is in the current head. - this._callback(null, { subject: prevItemHead, - predicate: RDF_REST, - object: itemHead, - graph: RVInnerN3Parser.prototype.defaultGraph }); - } - // Add the item's value. - if (item !== null) - this._callback(null, { subject: itemHead, - predicate: RDF_FIRST, - object: item, - graph: RVInnerN3Parser.prototype.defaultGraph }); - return next; - }, - - // ### `_readPunctuation` reads punctuation between triples or triple parts. - _readPunctuation: function (token, empty) { - var next; - switch (token.type) { - // A dot just ends the statement, without sharing anything with the next. - case 'dot': - next = this._readInTopContext; - break; - // Semicolon means the subject is shared; predicate and object are different. - case 'semicolon': - next = this._readPredicate; - break; - // Comma means both the subject and predicate are shared; the object is different. - case 'comma': - next = this._readObject; - break; - default: - return this._error('Expected punctuation to follow "' + this._object + '"', token); - } - // A triple has been completed now, so return it. - if (!empty) - this._callback(null, { subject: this._subject, - predicate: this._predicate, - object: this._object, - graph: RVInnerN3Parser.prototype.defaultGraph }); - return next; - }, + // Close the list by making the item head nil. + itemHead = RDF_NIL; + break; + default: + return this._error('Expected list item instead of "' + token.type + '"', token); + } - // ### `_readPrefix` reads the prefix of a prefix declaration. - _readPrefix: function (token) { - if (token.type !== 'prefix') - return this._error('Expected prefix to follow @prefix', token); - this._prefix = token.value; - return this._readPrefixURI; - }, + // Create a new blank node if no item head was assigned yet. + if (itemHead === null) + this._subject = itemHead = {'blank': '_:' + this._blankNodeCount++}; - // ### `_readPrefixURI` reads the URI of a prefix declaration. - _readPrefixURI: function (token) { - if (token.type !== 'explicituri') - return this._error('Expected explicituri to follow prefix "' + this.prefix + '"', token); - var prefixURI; - if (this._baseURI === null || absoluteURI.test(token.value)) - prefixURI = token.value; + // Is this the first element of the list? + if (prevItemHead === null) { + // This list is either the object or the subject. + if (parentTriple.object === RDF_NIL) + parentTriple.object = itemHead; else - prefixURI = this._resolveURI(token.value); - this._prefixes[this._prefix] = prefixURI; - this._prefixCallback(this._prefix, prefixURI); - return this._readDeclarationPunctuation; - }, + parentTriple.subject = itemHead; + } + else { + // The rest of the list is in the current head. + this._callback(null, { subject: prevItemHead, + predicate: RDF_REST, + object: itemHead, + graph: RVInnerN3Parser.prototype.defaultGraph }); + } + // Add the item's value. + if (item !== null) + this._callback(null, { subject: itemHead, + predicate: RDF_FIRST, + object: item, + graph: RVInnerN3Parser.prototype.defaultGraph }); + return next; + }, + + // ### `_readPunctuation` reads punctuation between triples or triple parts. + _readPunctuation: function (token, empty) { + var next; + switch (token.type) { + // A dot just ends the statement, without sharing anything with the next. + case 'dot': + next = this._readInTopContext; + break; + // Semicolon means the subject is shared; predicate and object are different. + case 'semicolon': + next = this._readPredicate; + break; + // Comma means both the subject and predicate are shared; the object is different. + case 'comma': + next = this._readObject; + break; + default: + return this._error('Expected punctuation to follow "' + this._object + '"', token); + } + // A triple has been completed now, so return it. + if (!empty) + this._callback(null, { subject: this._subject, + predicate: this._predicate, + object: this._object, + graph: RVInnerN3Parser.prototype.defaultGraph }); + return next; + }, + + // ### `_readPrefix` reads the prefix of a prefix declaration. + _readPrefix: function (token) { + if (token.type !== 'prefix') + return this._error('Expected prefix to follow @prefix', token); + this._prefix = token.value; + return this._readPrefixURI; + }, + + // ### `_readPrefixURI` reads the URI of a prefix declaration. + _readPrefixURI: function (token) { + if (token.type !== 'explicituri') + return this._error('Expected explicituri to follow prefix "' + this.prefix + '"', token); + var prefixURI; + if (this._baseURI === null || absoluteURI.test(token.value)) + prefixURI = token.value; + else + prefixURI = this._resolveURI(token.value); + this._prefixes[this._prefix] = prefixURI; + this._prefixCallback(this._prefix, prefixURI); + return this._readDeclarationPunctuation; + }, + + // ### `_readBaseURI` reads the URI of a base declaration. + _readBaseURI: function (token) { + if (token.type !== 'explicituri') + return this._error('Expected explicituri to follow base declaration', token); + if (this._baseURI === null || absoluteURI.test(token.value)) + this._baseURI = token.value; + else + this._baseURI = this._resolveURI(token.value); + this._baseURIPath = this._baseURI.replace(documentPart, ''); + this._baseURIRoot = this._baseURI.match(rootURI)[0]; + return this._readDeclarationPunctuation; + }, + + // ### `_readDeclarationPunctuation` reads the punctuation of a declaration. + _readDeclarationPunctuation: function (token) { + // SPARQL-style declarations don't have punctuation. + if (this._sparqlStyle) + return this._readInTopContext(token); + + if (token.type !== 'dot') + return this._error('Expected declaration to end with a dot', token); + return this._readInTopContext; + }, + + // ### `_getTripleEndReader` gets the next reader function at the end of a triple. + _getTripleEndReader: function () { + var stack = this._tripleStack; + if (stack.length === 0) + return this._readPunctuation; + + switch (stack[stack.length - 1].type) { + case 'blank': + return this._readBlankNodeTail; + case 'list': + return this._readListItem; + } + }, + + // ### `_error` emits an error message through the callback. + _error: function (message, token) { + this._callback(message + ' at line ' + token.line + '.'); + }, + + // ### `_resolveURI` resolves a URI against a base path + _resolveURI: function (uri) { + if (hashURI.test(uri)) + return this._baseURI + uri; + if (absolutePath.test(uri)) + return this._baseURIRoot + uri; + return this._baseURIPath + uri; + }, + + // ## Public methods + + // ### `parse` parses the N3 input and emits each parsed triple through the callback. + parse: function (input, tripleCallback, prefixCalback) { + var self = this; + // Initialize prefix declarations. + this._prefixes = {}; + // Set the triple and prefix callbacks. + this._callback = tripleCallback || noop; + this._prefixCallback = prefixCalback || noop; + // The read callback is the next function to be executed when a token arrives. + // We start reading in the top context. + this._readCallback = this._readInTopContext; + // Execute the read callback when a token arrives. + this._lexer.tokenize(input, function (error, token) { + if (self._readCallback !== _undefined) { + if (error !== null) + self._callback(error); + else + self._readCallback = self._readCallback(token); + } + }); + } +}; - // ### `_readBaseURI` reads the URI of a base declaration. - _readBaseURI: function (token) { - if (token.type !== 'explicituri') - return this._error('Expected explicituri to follow base declaration', token); - if (this._baseURI === null || absoluteURI.test(token.value)) - this._baseURI = token.value; - else - this._baseURI = this._resolveURI(token.value); - this._baseURIPath = this._baseURI.replace(documentPart, ''); - this._baseURIRoot = this._baseURI.match(rootURI)[0]; - return this._readDeclarationPunctuation; - }, +/* +var RDF_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + RDF_NIL = {token: 'uri', value: RDF_PREFIX + 'nil', prefix: null, suffix: null}, + RDF_FIRST = {token: 'uri', value: RDF_PREFIX + 'first', prefix: null, suffix: null}, + RDF_REST = {token: 'uri', value: RDF_PREFIX + 'rest', prefix: null, suffix: null}; - // ### `_readDeclarationPunctuation` reads the punctuation of a declaration. - _readDeclarationPunctuation: function (token) { - // SPARQL-style declarations don't have punctuation. - if (this._sparqlStyle) - return this._readInTopContext(token); +var absoluteURI = /^[a-z]+:/; +var hashURI = /^#/; +var documentPart = /[^\/]*$/; - if (token.type !== 'dot') - return this._error('Expected declaration to end with a dot', token); - return this._readInTopContext; - }, +var _undefined; - // ### `_getTripleEndReader` gets the next reader function at the end of a triple. - _getTripleEndReader: function () { - var stack = this._tripleStack; - if (stack.length === 0) - return this._readPunctuation; +// ## Constructor +function RVInnerN3Parser(config) { + config = config || {}; + + // We use a dummy constructor to enable construction without `new`. + function Constructor() {} + Constructor.prototype = RVInnerN3Parser.prototype; + + // Initialize the new `RVInnerN3Parser`. + var n3Parser = new Constructor(); + n3Parser._lexer = config.lexer || new N3Lexer(); + n3Parser._blankNodes = Object.create(null); + n3Parser._blankNodeCount = 0; + n3Parser._tripleStack = []; + if (!config.documentURI) { + n3Parser._baseURI = n3Parser._documentURI = null; + n3Parser._baseURIROOT = n3Parser._documentURIRoot = null; + } + else { + n3Parser._baseURI = n3Parser._documentURI = config.documentURI; + n3Parser._baseURIRoot = n3Parser._documentURIRoot = config.documentURI.replace(documentPart, ''); + } - switch (stack[stack.length - 1].type) { - case 'blank': - return this._readBlankNodeTail; - case 'list': - return this._readListItem; + // Return the new `RVInnerN3Parser`. + return n3Parser; +} + +RVInnerN3Parser.prototype = { + defaultGraph: null, + constructor: RVInnerN3Parser, + + // ## Private methods + + // ### `_readInTopContext` reads a token when in the top context. + _readInTopContext: function (token) { + switch (token.type) { + // If an EOF token arrives in the top context, signal that we're done. + case 'eof': + return this._callback(null, null); + // It could be a prefix declaration. + case '@prefix': + this._sparqlStyle = false; + return this._readPrefix; + case 'PREFIX': + this._sparqlStyle = true; + return this._readPrefix; + // It could be a base declaration. + case '@base': + this._sparqlStyle = false; + return this._readBaseURI; + case 'BASE': + this._sparqlStyle = true; + return this._readBaseURI; + // Otherwise, the next token must be a subject. + default: + return this._readSubject(token); + } + }, + + // ### `_readSubject` reads a triple's subject. + _readSubject: function (token) { + switch (token.type) { + case 'explicituri': + if (this._baseURI === null || absoluteURI.test(token.value)) + this._subject = {token: 'uri', value: token.value, prefix: null, suffix: null}; + else + this._subject = {token: 'uri', value: (hashURI.test(token.value) ? this._baseURI : this._baseURIRoot) + token.value, prefix: null, suffix: null}; + break; + case 'qname': + if (token.prefix === '_') { + if(this._blankNodes[token.value] !== undefined) { + this._subject = {'blank': this._blankNodes[token.value] }; + } else { + this._subject = {'blank': (this._blankNodes[token.value] = '_:' + this._blankNodeCount++)}; + } } - }, - - // ### `_error` emits an error message through the callback. - _error: function (message, token) { - this._callback(message + ' at line ' + token.line + '.'); - }, - - // ### `_resolveURI` resolves a URI against a base path - _resolveURI: function (uri) { - if (hashURI.test(uri)) - return this._baseURI + uri; - if (absolutePath.test(uri)) - return this._baseURIRoot + uri; - return this._baseURIPath + uri; - }, - - // ## Public methods - - // ### `parse` parses the N3 input and emits each parsed triple through the callback. - parse: function (input, tripleCallback, prefixCalback) { - var self = this; - // Initialize prefix declarations. - this._prefixes = {}; - // Set the triple and prefix callbacks. - this._callback = tripleCallback || noop; - this._prefixCallback = prefixCalback || noop; - // The read callback is the next function to be executed when a token arrives. - // We start reading in the top context. - this._readCallback = this._readInTopContext; - // Execute the read callback when a token arrives. - this._lexer.tokenize(input, function (error, token) { - if (self._readCallback !== _undefined) { - if (error !== null) - self._callback(error); - else - self._readCallback = self._readCallback(token); + else { + var prefix = this._prefixes[token.prefix]; + if (prefix === _undefined) + return this._error('Undefined prefix "' + token.prefix + ':"', token); + this._subject = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; + } + break; + case 'bracketopen': + // Start a new triple with a new blank node as subject. + this._subject = {'blank': ('_:' + this._blankNodeCount++)}; + this._tripleStack.push({ subject: this._subject, predicate: null, object: null, type: 'blank' }); + return this._readBlankNodeHead; + case 'liststart': + // Start a new list + this._tripleStack.push({ subject: RDF_NIL, predicate: null, object: null, type: 'list' }); + this._subject = null; + return this._readListItem; + default: + return this._error('Unexpected token type "' + token.type, token); + } + this._subjectHasPredicate = false; + // The next token must be a predicate. + return this._readPredicate; + }, + + // ### `_readPredicate` reads a triple's predicate. + _readPredicate: function (token) { + switch (token.type) { + case 'explicituri': + case 'abbreviation': + if (this._baseURI === null || absoluteURI.test(token.value)) + this._predicate = {token: 'uri', value: token.value, prefix: null, suffix: null}; + else + this._predicate = {token: 'uri', value: (hashURI.test(token.value) ? this._baseURI : this._baseURIRoot) + token.value, prefix: null, suffix: null}; + break; + case 'qname': + if (token.prefix === '_') { + return this._error('Disallowed blank node as predicate', token); + } + else { + var prefix = this._prefixes[token.prefix]; + if (prefix === _undefined) + return this._error('Undefined prefix "' + token.prefix + ':"', token); + this._predicate = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; + } + break; + case 'bracketclose': + // Expected predicate didn't come, must have been trailing semicolon. + return this._readBlankNodeTail(token, true); + case 'dot': + // A dot is not allowed if the subject did not have a predicate yet + if (!this._subjectHasPredicate) + return this._error('Unexpected dot', token); + // Expected predicate didn't come, must have been trailing semicolon. + return this._readPunctuation(token, true); + case 'semicolon': + // Extra semicolons can be safely ignored + return this._readPredicate; + default: + return this._error('Expected predicate to follow "' + this._subject + '"', token); + } + this._subjectHasPredicate = true; + // The next token must be an object. + return this._readObject; + }, + + // ### `_readObject` reads a triple's object. + _readObject: function (token) { + switch (token.type) { + case 'explicituri': + if (this._baseURI === null || absoluteURI.test(token.value)) + this._object = {token: 'uri', value: token.value, prefix: null, suffix: null}; + else + this._object = {token: 'uri', value: (hashURI.test(token.value) ? this._baseURI : this._baseURIRoot) + token.value, prefix: null, suffix: null}; + break; + case 'qname': + if (token.prefix === '_') { + if(this._blankNodes[token.value] !== undefined) { + this._object = {'blank': this._blankNodes[token.value] }; + } else { + this._object = {'blank': (this._blankNodes[token.value] = '_:' + this._blankNodeCount++)}; + } + } + else { + var prefix = this._prefixes[token.prefix]; + if (prefix === _undefined) + return this._error('Undefined prefix "' + token.prefix + ':"', token); + this._object = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; + } + break; + case 'literal': + this._object = {'literal': token.value}; + return this._readDataTypeOrLang; + case 'bracketopen': + // Start a new triple with a new blank node as subject. + var blank = {'blank': '_:' + this._blankNodeCount++}; + this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: blank, type: 'blank' }); + this._subject = blank; + return this._readBlankNodeHead; + case 'liststart': + // Start a new list + this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: RDF_NIL, type: 'list' }); + this._subject = null; + return this._readListItem; + default: + return this._error('Expected object to follow "' + this._predicate + '"', token); + } + return this._getNextReader(); + }, + + // ### `_readBlankNodeHead` reads the head of a blank node. + _readBlankNodeHead: function (token) { + if (token.type === 'bracketclose') + return this._readBlankNodeTail(token, true); + else + return this._readPredicate(token); + }, + + // ### `_readBlankNodeTail` reads the end of a blank node. + _readBlankNodeTail: function (token, empty) { + if (token.type !== 'bracketclose') + return this._readPunctuation(token); + + // Store blank node triple. + if (empty !== true) + this._callback(null, { subject: this._subject, + predicate: this._predicate, + object: this._object, + graph: RVInnerN3Parser.prototype.defaultGraph }); + + // Restore parent triple that contains the blank node. + var triple = this._tripleStack.pop(); + this._subject = triple.subject; + // Was the blank node the object? + if (triple.object !== null) { + // Restore predicate and object as well, and continue by reading punctuation. + this._predicate = triple.predicate; + this._object = triple.object; + return this._getNextReader(); + } + // The blank node was the subject, so continue reading the predicate. + return this._readPredicate; + }, + + // ### `_readDataTypeOrLang` reads an _optional_ data type or language. + _readDataTypeOrLang: function (token) { + switch (token.type) { + case 'type': + var value; + if (token.prefix === '') { + value = token.value; + } + else { + var prefix = this._prefixes[token.prefix]; + if (prefix === _undefined) + return this._error('Undefined prefix "' + token.prefix + ':"', token); + value = prefix + token.value; + } + if(this._object.literal) { + this._object.literal += '^^<' + value + '>'; + } else { + this._object += '^^<' + value + '>'; + this._object = {literal: this._object}; + } + return this._readPunctuation; + case 'langcode': + if(this._object.literal) { + this._object.literal += '@' + token.value.toLowerCase(); + } else { + this._object += '@' + token.value.toLowerCase(); + this._object = {literal: this._object}; } - }); + return this._getNextReader(); + default: + return this._getNextReader().call(this, token); } - }; - - /* - var RDF_PREFIX = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', - RDF_NIL = {token: 'uri', value: RDF_PREFIX + 'nil', prefix: null, suffix: null}, - RDF_FIRST = {token: 'uri', value: RDF_PREFIX + 'first', prefix: null, suffix: null}, - RDF_REST = {token: 'uri', value: RDF_PREFIX + 'rest', prefix: null, suffix: null}; - - var absoluteURI = /^[a-z]+:/; - var hashURI = /^#/; - var documentPart = /[^\/]*$/; - - var _undefined; - - // ## Constructor - function RVInnerN3Parser(config) { - config = config || {}; - - // We use a dummy constructor to enable construction without `new`. - function Constructor() {} - Constructor.prototype = RVInnerN3Parser.prototype; - - // Initialize the new `RVInnerN3Parser`. - var n3Parser = new Constructor(); - n3Parser._lexer = config.lexer || new N3Lexer(); - n3Parser._blankNodes = Object.create(null); - n3Parser._blankNodeCount = 0; - n3Parser._tripleStack = []; - if (!config.documentURI) { - n3Parser._baseURI = n3Parser._documentURI = null; - n3Parser._baseURIROOT = n3Parser._documentURIRoot = null; - } - else { - n3Parser._baseURI = n3Parser._documentURI = config.documentURI; - n3Parser._baseURIRoot = n3Parser._documentURIRoot = config.documentURI.replace(documentPart, ''); - } - - // Return the new `RVInnerN3Parser`. - return n3Parser; - } - - RVInnerN3Parser.prototype = { - defaultGraph: null, - constructor: RVInnerN3Parser, - - // ## Private methods - - // ### `_readInTopContext` reads a token when in the top context. - _readInTopContext: function (token) { - switch (token.type) { - // If an EOF token arrives in the top context, signal that we're done. - case 'eof': - return this._callback(null, null); - // It could be a prefix declaration. - case '@prefix': - this._sparqlStyle = false; - return this._readPrefix; - case 'PREFIX': - this._sparqlStyle = true; - return this._readPrefix; - // It could be a base declaration. - case '@base': - this._sparqlStyle = false; - return this._readBaseURI; - case 'BASE': - this._sparqlStyle = true; - return this._readBaseURI; - // Otherwise, the next token must be a subject. - default: - return this._readSubject(token); - } - }, - - // ### `_readSubject` reads a triple's subject. - _readSubject: function (token) { - switch (token.type) { - case 'explicituri': - if (this._baseURI === null || absoluteURI.test(token.value)) - this._subject = {token: 'uri', value: token.value, prefix: null, suffix: null}; - else - this._subject = {token: 'uri', value: (hashURI.test(token.value) ? this._baseURI : this._baseURIRoot) + token.value, prefix: null, suffix: null}; - break; - case 'qname': - if (token.prefix === '_') { - if(this._blankNodes[token.value] !== undefined) { - this._subject = {'blank': this._blankNodes[token.value] }; - } else { - this._subject = {'blank': (this._blankNodes[token.value] = '_:' + this._blankNodeCount++)}; - } - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === _undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._subject = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; - } - break; - case 'bracketopen': - // Start a new triple with a new blank node as subject. - this._subject = {'blank': ('_:' + this._blankNodeCount++)}; - this._tripleStack.push({ subject: this._subject, predicate: null, object: null, type: 'blank' }); - return this._readBlankNodeHead; - case 'liststart': - // Start a new list - this._tripleStack.push({ subject: RDF_NIL, predicate: null, object: null, type: 'list' }); - this._subject = null; - return this._readListItem; - default: - return this._error('Unexpected token type "' + token.type, token); - } - this._subjectHasPredicate = false; - // The next token must be a predicate. - return this._readPredicate; - }, - - // ### `_readPredicate` reads a triple's predicate. - _readPredicate: function (token) { - switch (token.type) { - case 'explicituri': - case 'abbreviation': - if (this._baseURI === null || absoluteURI.test(token.value)) - this._predicate = {token: 'uri', value: token.value, prefix: null, suffix: null}; - else - this._predicate = {token: 'uri', value: (hashURI.test(token.value) ? this._baseURI : this._baseURIRoot) + token.value, prefix: null, suffix: null}; - break; - case 'qname': - if (token.prefix === '_') { - return this._error('Disallowed blank node as predicate', token); - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === _undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._predicate = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; - } - break; - case 'bracketclose': - // Expected predicate didn't come, must have been trailing semicolon. - return this._readBlankNodeTail(token, true); - case 'dot': - // A dot is not allowed if the subject did not have a predicate yet - if (!this._subjectHasPredicate) - return this._error('Unexpected dot', token); - // Expected predicate didn't come, must have been trailing semicolon. - return this._readPunctuation(token, true); - case 'semicolon': - // Extra semicolons can be safely ignored - return this._readPredicate; - default: - return this._error('Expected predicate to follow "' + this._subject + '"', token); - } - this._subjectHasPredicate = true; - // The next token must be an object. - return this._readObject; - }, - - // ### `_readObject` reads a triple's object. - _readObject: function (token) { - switch (token.type) { - case 'explicituri': - if (this._baseURI === null || absoluteURI.test(token.value)) - this._object = {token: 'uri', value: token.value, prefix: null, suffix: null}; - else - this._object = {token: 'uri', value: (hashURI.test(token.value) ? this._baseURI : this._baseURIRoot) + token.value, prefix: null, suffix: null}; - break; - case 'qname': - if (token.prefix === '_') { - if(this._blankNodes[token.value] !== undefined) { - this._object = {'blank': this._blankNodes[token.value] }; - } else { - this._object = {'blank': (this._blankNodes[token.value] = '_:' + this._blankNodeCount++)}; - } - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === _undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - this._object = {token: 'uri', value: prefix + token.value, prefix: null, suffix: null}; - } - break; - case 'literal': - this._object = {'literal': token.value}; - return this._readDataTypeOrLang; - case 'bracketopen': - // Start a new triple with a new blank node as subject. - var blank = {'blank': '_:' + this._blankNodeCount++}; - this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: blank, type: 'blank' }); - this._subject = blank; - return this._readBlankNodeHead; - case 'liststart': - // Start a new list - this._tripleStack.push({ subject: this._subject, predicate: this._predicate, object: RDF_NIL, type: 'list' }); - this._subject = null; - return this._readListItem; - default: - return this._error('Expected object to follow "' + this._predicate + '"', token); - } - return this._getNextReader(); - }, - - // ### `_readBlankNodeHead` reads the head of a blank node. - _readBlankNodeHead: function (token) { - if (token.type === 'bracketclose') - return this._readBlankNodeTail(token, true); - else - return this._readPredicate(token); - }, - - // ### `_readBlankNodeTail` reads the end of a blank node. - _readBlankNodeTail: function (token, empty) { - if (token.type !== 'bracketclose') - return this._readPunctuation(token); - - // Store blank node triple. - if (empty !== true) - this._callback(null, { subject: this._subject, - predicate: this._predicate, - object: this._object, - graph: RVInnerN3Parser.prototype.defaultGraph }); - - // Restore parent triple that contains the blank node. - var triple = this._tripleStack.pop(); - this._subject = triple.subject; - // Was the blank node the object? - if (triple.object !== null) { - // Restore predicate and object as well, and continue by reading punctuation. - this._predicate = triple.predicate; - this._object = triple.object; - return this._getNextReader(); - } - // The blank node was the subject, so continue reading the predicate. - return this._readPredicate; - }, - - // ### `_readDataTypeOrLang` reads an _optional_ data type or language. - _readDataTypeOrLang: function (token) { - switch (token.type) { - case 'type': - var value; - if (token.prefix === '') { - value = token.value; - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === _undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - value = prefix + token.value; - } - if(this._object.literal) { - this._object.literal += '^^<' + value + '>'; - } else { - this._object += '^^<' + value + '>'; - this._object = {literal: this._object}; - } - return this._readPunctuation; - case 'langcode': - if(this._object.literal) { - this._object.literal += '@' + token.value.toLowerCase(); - } else { - this._object += '@' + token.value.toLowerCase(); - this._object = {literal: this._object}; - } - return this._getNextReader(); - default: - return this._getNextReader().call(this, token); - } - }, - - // ### `_readListItem` reads items from a list. - _readListItem: function (token) { - var item = null, // The actual list item. - itemHead = null, // The head of the rdf:first predicate. - prevItemHead = this._subject, // The head of the previous rdf:first predicate. - stack = this._tripleStack, // The stack of triples part of recursion (lists, blanks, etc.). - parentTriple = stack[stack.length - 1], // The triple containing the current list. - next = this._readListItem; // The next function to execute. - - switch (token.type) { - case 'explicituri': - item = {'token': 'uri', 'value': token.value, 'prefix': null, 'suffix': null}; - break; - case 'qname': - if (token.prefix === '_') { - item = this._blankNodes[token.value] || - (this._blankNodes[token.value] = {'blank': '_:' + this._blankNodeCount++}); - } - else { - var prefix = this._prefixes[token.prefix]; - if (prefix === _undefined) - return this._error('Undefined prefix "' + token.prefix + ':"', token); - item = {'token': 'uri', 'value': prefix + token.value, 'prefix': null, 'suffix': null}; - } - break; - case 'literal': - item = {'literal': token.value }; - next = this._readDataTypeOrLang; - break; - case 'bracketopen': - // Stack the current list triple and start a new triple with a blank node as subject. - itemHead = {'blank': '_:' + this._blankNodeCount++ }; - item = {'blank': '_:' + this._blankNodeCount++ }; - stack.push({ subject: itemHead, predicate: RDF_FIRST, object: item, type: 'blank' }); - this._subject = item; - next = this._readBlankNodeHead; - break; - case 'liststart': - // Stack the current list triple and start a new list - itemHead = {'blank': '_:' + this._blankNodeCount++}; - stack.push({ subject: itemHead, predicate: RDF_FIRST, object: RDF_NIL, type: 'list' }); - this._subject = null; - next = this._readListItem; - break; - case 'listend': - // Restore the parent triple. - stack.pop(); - // If this list is contained within a parent list, return the membership triple here. - // This will be `t rdf:first .`. - if (stack.length !== 0 && stack[stack.length - 1].type === 'list') - this._callback(null, { subject: parentTriple.subject, - predicate: parentTriple.predicate, - object: parentTriple.object, - graph: RVInnerN3Parser.prototype.defaultGraph }); - // Restore the parent triple's subject. - this._subject = (typeof(parentTriple.subject) === 'string' ? {'token': 'uri', 'value': parentTriple.subject, 'prefix': null, 'suffix': null } : parentTriple.subject); - // Was this list in the parent triple's subject? - if (parentTriple.predicate === null) { - // The next token is the predicate. - next = this._readPredicate; - // Skip writing the list tail if this was an empty list. - if (parentTriple.subject === RDF_NIL) - return next; - } - // The list was in the parent triple's object. - else { - // Restore the parent triple's predicate and object as well. - this._predicate = (typeof(parentTriple.predicate) === 'string' ? {'token': 'uri', 'value': parentTriple.predicate, 'prefix': null, 'suffix': null } : parentTriple.predicate); - this._object = (typeof(parentTriple.object) === 'string' ? {'token': 'uri', 'value': parentTriple.object, 'prefix': null, 'suffix': null } : parentTriple.object); - next = this._getNextReader(); - // Skip writing the list tail if this was an empty list. - if (parentTriple.object === RDF_NIL) - return next; - } - // Close the list by making the item head nil. - itemHead = RDF_NIL; - break; - default: - return this._error('Expected list item instead of "' + token.type + '"', token); - } + }, - // Create a new blank node if no item head was assigned yet. - if (itemHead === null) - this._subject = itemHead = {'blank': '_:' + this._blankNodeCount++}; - - // Is this the first element of the list? - if (prevItemHead === null) { - // This list is either the object or the subject. - if (parentTriple.object === RDF_NIL) - parentTriple.object = itemHead; - else - parentTriple.subject = itemHead; - } - else { - // The rest of the list is in the current head. - this._callback(null, { subject: prevItemHead, - predicate: RDF_REST, - object: itemHead, - graph: RVInnerN3Parser.prototype.defaultGraph }); - } - // Add the item's value. - if (item !== null) - this._callback(null, { subject: itemHead, - predicate: RDF_FIRST, - object: item, - graph: RVInnerN3Parser.prototype.defaultGraph }); - return next; - }, - - // ### `_readPunctuation` reads punctuation between triples or triple parts. - _readPunctuation: function (token, empty) { - var next; - switch (token.type) { - // A dot just ends the statement, without sharing anything with the next. - case 'dot': - next = this._readInTopContext; - break; - // Semicolon means the subject is shared; predicate and object are different. - case 'semicolon': - next = this._readPredicate; - break; - // Comma means both the subject and predicate are shared; the object is different. - case 'comma': - next = this._readObject; - break; - default: - return this._error('Expected punctuation to follow "' + this._object + '"', token); - } - // A triple has been completed now, so return it. - if (!empty) - this._callback(null, { subject: this._subject, - predicate: this._predicate, - object: this._object, - graph: RVInnerN3Parser.prototype.defaultGraph }); - return next; - }, - - // ### `_readPrefix` reads the prefix of a prefix declaration. - _readPrefix: function (token) { - if (token.type !== 'prefix') - return this._error('Expected prefix to follow @prefix', token); - this._prefix = token.value; - return this._readPrefixURI; - }, - - // ### `_readPrefixURI` reads the URI of a prefix declaration. - _readPrefixURI: function (token) { - if (token.type !== 'explicituri') - return this._error('Expected explicituri to follow prefix "' + this.prefix + '"', token); - var prefixURI; - if (this._baseURI === null || absoluteURI.test(token.value)) - prefixURI = token.value; - else - prefixURI = (hashURI.test(token.value) ? this._baseURI : this._baseURIRoot) + token.value; - this._prefixes[this._prefix] = prefixURI; - return this._readDeclarationPunctuation; - }, - - // ### `_readBaseURI` reads the URI of a base declaration. - _readBaseURI: function (token) { - if (token.type !== 'explicituri') - return this._error('Expected explicituri to follow base declaration', token); - if (this._baseURI === null || absoluteURI.test(token.value)) - this._baseURI = token.value; - else - this._baseURI = (hashURI.test(token.value) ? this._baseURI : this._baseURIRoot) + token.value; - this._baseURIRoot = this._baseURI.replace(documentPart, ''); - return this._readDeclarationPunctuation; - }, - - // ### `_readDeclarationPunctuation` reads the punctuation of a declaration. - _readDeclarationPunctuation: function (token) { - // SPARQL-style declarations don't have punctuation. - if (this._sparqlStyle) - return this._readInTopContext(token); - - if (token.type !== 'dot') - return this._error('Expected declaration to end with a dot', token); - return this._readInTopContext; - }, - - // ### `_getNextReader` gets the next reader function at the end of a triple. - _getNextReader: function () { - var stack = this._tripleStack; - if (stack.length === 0) - return this._readPunctuation; - - switch (stack[stack.length - 1].type) { - case 'blank': - return this._readBlankNodeTail; - case 'list': - return this._readListItem; - } - }, + // ### `_readListItem` reads items from a list. + _readListItem: function (token) { + var item = null, // The actual list item. + itemHead = null, // The head of the rdf:first predicate. + prevItemHead = this._subject, // The head of the previous rdf:first predicate. + stack = this._tripleStack, // The stack of triples part of recursion (lists, blanks, etc.). + parentTriple = stack[stack.length - 1], // The triple containing the current list. + next = this._readListItem; // The next function to execute. - // ### `_error` emits an error message through the callback. - _error: function (message, token) { - this._callback(message + ' at line ' + token.line + '.'); - }, + switch (token.type) { + case 'explicituri': + item = {'token': 'uri', 'value': token.value, 'prefix': null, 'suffix': null}; + break; + case 'qname': + if (token.prefix === '_') { + item = this._blankNodes[token.value] || + (this._blankNodes[token.value] = {'blank': '_:' + this._blankNodeCount++}); + } + else { + var prefix = this._prefixes[token.prefix]; + if (prefix === _undefined) + return this._error('Undefined prefix "' + token.prefix + ':"', token); + item = {'token': 'uri', 'value': prefix + token.value, 'prefix': null, 'suffix': null}; + } + break; + case 'literal': + item = {'literal': token.value }; + next = this._readDataTypeOrLang; + break; + case 'bracketopen': + // Stack the current list triple and start a new triple with a blank node as subject. + itemHead = {'blank': '_:' + this._blankNodeCount++ }; + item = {'blank': '_:' + this._blankNodeCount++ }; + stack.push({ subject: itemHead, predicate: RDF_FIRST, object: item, type: 'blank' }); + this._subject = item; + next = this._readBlankNodeHead; + break; + case 'liststart': + // Stack the current list triple and start a new list + itemHead = {'blank': '_:' + this._blankNodeCount++}; + stack.push({ subject: itemHead, predicate: RDF_FIRST, object: RDF_NIL, type: 'list' }); + this._subject = null; + next = this._readListItem; + break; + case 'listend': + // Restore the parent triple. + stack.pop(); + // If this list is contained within a parent list, return the membership triple here. + // This will be `t rdf:first .`. + if (stack.length !== 0 && stack[stack.length - 1].type === 'list') + this._callback(null, { subject: parentTriple.subject, + predicate: parentTriple.predicate, + object: parentTriple.object, + graph: RVInnerN3Parser.prototype.defaultGraph }); + // Restore the parent triple's subject. + this._subject = (typeof(parentTriple.subject) === 'string' ? {'token': 'uri', 'value': parentTriple.subject, 'prefix': null, 'suffix': null } : parentTriple.subject); + // Was this list in the parent triple's subject? + if (parentTriple.predicate === null) { + // The next token is the predicate. + next = this._readPredicate; + // Skip writing the list tail if this was an empty list. + if (parentTriple.subject === RDF_NIL) + return next; + } + // The list was in the parent triple's object. + else { + // Restore the parent triple's predicate and object as well. + this._predicate = (typeof(parentTriple.predicate) === 'string' ? {'token': 'uri', 'value': parentTriple.predicate, 'prefix': null, 'suffix': null } : parentTriple.predicate); + this._object = (typeof(parentTriple.object) === 'string' ? {'token': 'uri', 'value': parentTriple.object, 'prefix': null, 'suffix': null } : parentTriple.object); + next = this._getNextReader(); + // Skip writing the list tail if this was an empty list. + if (parentTriple.object === RDF_NIL) + return next; + } + // Close the list by making the item head nil. + itemHead = RDF_NIL; + break; + default: + return this._error('Expected list item instead of "' + token.type + '"', token); + } - // ## Public methods + // Create a new blank node if no item head was assigned yet. + if (itemHead === null) + this._subject = itemHead = {'blank': '_:' + this._blankNodeCount++}; - // ### `parse` parses the N3 input and emits each parsed triple through the callback. - parse: function (input, callback) { - var self = this; - // Initialize prefix declarations. - this._prefixes = Object.create(null); - // Set the triple callback. - this._callback = callback; - // The read callback is the next function to be executed when a token arrives. - // We start reading in the top context. - this._readCallback = this._readInTopContext; - // Execute the read callback when a token arrives. - this._lexer.tokenize(input, function (error, token) { - if(error !== null && self._readCallback === _undefined) { - self._callback(error); - } else if (self._readCallback !== _undefined) { - if (error !== null) - self._callback(error); - else - self._readCallback = self._readCallback(token); - } - }); - } - }; - */ + // Is this the first element of the list? + if (prevItemHead === null) { + // This list is either the object or the subject. + if (parentTriple.object === RDF_NIL) + parentTriple.object = itemHead; + else + parentTriple.subject = itemHead; + } + else { + // The rest of the list is in the current head. + this._callback(null, { subject: prevItemHead, + predicate: RDF_REST, + object: itemHead, + graph: RVInnerN3Parser.prototype.defaultGraph }); + } + // Add the item's value. + if (item !== null) + this._callback(null, { subject: itemHead, + predicate: RDF_FIRST, + object: item, + graph: RVInnerN3Parser.prototype.defaultGraph }); + return next; + }, + + // ### `_readPunctuation` reads punctuation between triples or triple parts. + _readPunctuation: function (token, empty) { + var next; + switch (token.type) { + // A dot just ends the statement, without sharing anything with the next. + case 'dot': + next = this._readInTopContext; + break; + // Semicolon means the subject is shared; predicate and object are different. + case 'semicolon': + next = this._readPredicate; + break; + // Comma means both the subject and predicate are shared; the object is different. + case 'comma': + next = this._readObject; + break; + default: + return this._error('Expected punctuation to follow "' + this._object + '"', token); + } + // A triple has been completed now, so return it. + if (!empty) + this._callback(null, { subject: this._subject, + predicate: this._predicate, + object: this._object, + graph: RVInnerN3Parser.prototype.defaultGraph }); + return next; + }, + + // ### `_readPrefix` reads the prefix of a prefix declaration. + _readPrefix: function (token) { + if (token.type !== 'prefix') + return this._error('Expected prefix to follow @prefix', token); + this._prefix = token.value; + return this._readPrefixURI; + }, + + // ### `_readPrefixURI` reads the URI of a prefix declaration. + _readPrefixURI: function (token) { + if (token.type !== 'explicituri') + return this._error('Expected explicituri to follow prefix "' + this.prefix + '"', token); + var prefixURI; + if (this._baseURI === null || absoluteURI.test(token.value)) + prefixURI = token.value; + else + prefixURI = (hashURI.test(token.value) ? this._baseURI : this._baseURIRoot) + token.value; + this._prefixes[this._prefix] = prefixURI; + return this._readDeclarationPunctuation; + }, + + // ### `_readBaseURI` reads the URI of a base declaration. + _readBaseURI: function (token) { + if (token.type !== 'explicituri') + return this._error('Expected explicituri to follow base declaration', token); + if (this._baseURI === null || absoluteURI.test(token.value)) + this._baseURI = token.value; + else + this._baseURI = (hashURI.test(token.value) ? this._baseURI : this._baseURIRoot) + token.value; + this._baseURIRoot = this._baseURI.replace(documentPart, ''); + return this._readDeclarationPunctuation; + }, + + // ### `_readDeclarationPunctuation` reads the punctuation of a declaration. + _readDeclarationPunctuation: function (token) { + // SPARQL-style declarations don't have punctuation. + if (this._sparqlStyle) + return this._readInTopContext(token); + + if (token.type !== 'dot') + return this._error('Expected declaration to end with a dot', token); + return this._readInTopContext; + }, + + // ### `_getNextReader` gets the next reader function at the end of a triple. + _getNextReader: function () { + var stack = this._tripleStack; + if (stack.length === 0) + return this._readPunctuation; + + switch (stack[stack.length - 1].type) { + case 'blank': + return this._readBlankNodeTail; + case 'list': + return this._readListItem; + } + }, + + // ### `_error` emits an error message through the callback. + _error: function (message, token) { + this._callback(message + ' at line ' + token.line + '.'); + }, + + // ## Public methods + + // ### `parse` parses the N3 input and emits each parsed triple through the callback. + parse: function (input, callback) { + var self = this; + // Initialize prefix declarations. + this._prefixes = Object.create(null); + // Set the triple callback. + this._callback = callback; + // The read callback is the next function to be executed when a token arrives. + // We start reading in the top context. + this._readCallback = this._readInTopContext; + // Execute the read callback when a token arrives. + this._lexer.tokenize(input, function (error, token) { + if(error !== null && self._readCallback === _undefined) { + self._callback(error); + } else if (self._readCallback !== _undefined) { + if (error !== null) + self._callback(error); + else + self._readCallback = self._readCallback(token); + } + }); + } +}; +*/ // ## Exports // Export the `RVInnerN3Parser` class as a whole. - var RVN3Parser = {}; +var RVN3Parser = {}; - RVN3Parser.parser = {}; +RVN3Parser.parser = {}; // The parser is asynchronous - RVN3Parser.parser.async = true; +RVN3Parser.parser.async = true; - RVN3Parser.parser.parse = function() { +RVN3Parser.parser.parse = function() { var data = arguments[0]; @@ -7040,168 +6475,168 @@ var cb = arguments[3]; if(arguments.length === 3) { - graph = null; - options = arguments[1]; - cb = arguments[2]; + graph = null; + options = arguments[1]; + cb = arguments[2]; } else if(arguments.length !== 4) { - cb(false, "Wrong number of arguments, 3, 4 args required"); + cb(false, "Wrong number of arguments, 3, 4 args required"); } if(graph && typeof(graph) === 'string') - graph = {token: 'uri', value: graph, prefix: null, suffix: null}; + graph = {token: 'uri', value: graph, prefix: null, suffix: null}; var parser = new RVInnerN3Parser(options); RVInnerN3Parser.prototype.defaultGraph = graph; var triples = []; - parser.parse(data, function(err,triple) { - if(err) { - cb(false, err); - } else { - if(triple) { - triples.push(triple); + parser.parse(data, function(err,triple) { + if(err) { + cb(false, err); } else { - cb(true, triples); + if(triple) { + triples.push(triple); + } else { + cb(true, triples); + } } - } - }); - }; + }); +}; // end of ./src/js-communication/src/rvn3_parser.js // exports - var RDFLoader = {}; +var RDFLoader = {}; // imports - var N3Parser = RVN3Parser; - RDFLoader.RDFLoader = function (params) { +var N3Parser = RVN3Parser; +RDFLoader.RDFLoader = function (params) { this.precedences = ["text/turtle", "text/n3", "application/ld+json", "application/json"/*, "application/rdf+xml"*/]; this.parsers = {"text/turtle":N3Parser.parser, "text/n3":N3Parser.parser, "application/ld+json":JSONLDParser.parser, "application/json":JSONLDParser.parser/*, "application/rdf+xml":RDFXMLParser.parser*/}; if (params != null) { - for (var mime in params["parsers"]) { - this.parsers[mime] = params["parsers"][mime]; - } + for (var mime in params["parsers"]) { + this.parsers[mime] = params["parsers"][mime]; + } } if (params && params["precedences"] != null) { - this.precedences = params["precedences"]; - for (var mime in params["parsers"]) { - if (!Utils.include(this.precedences, mime)) { - this.precedences.push(mime); + this.precedences = params["precedences"]; + for (var mime in params["parsers"]) { + if (!Utils.include(this.precedences, mime)) { + this.precedences.push(mime); + } } - } } this.acceptHeaderValue = ""; for (var i = 0; i < this.precedences.length; i++) { - if (i != 0) { - this.acceptHeaderValue = this.acceptHeaderValue + "," + this.precedences[i]; - } else { - this.acceptHeaderValue = this.acceptHeaderValue + this.precedences[i]; - } + if (i != 0) { + this.acceptHeaderValue = this.acceptHeaderValue + "," + this.precedences[i]; + } else { + this.acceptHeaderValue = this.acceptHeaderValue + this.precedences[i]; + } } - }; +}; - RDFLoader.RDFLoader.prototype.registerParser = function(mediaType, parser) { +RDFLoader.RDFLoader.prototype.registerParser = function(mediaType, parser) { this.parsers[mediaType] = parser; this.precedences.push(mediaType); - }; +}; - RDFLoader.RDFLoader.prototype.unregisterParser = function(mediaType) { +RDFLoader.RDFLoader.prototype.unregisterParser = function(mediaType) { delete this.parsers[mediaType]; var mediaTypes = []; for(var i=0; i - * W3C's note - */ - AbstractQueryTree.AbstractQueryTree = function() { - }; +/** + * @doc + * + * Based on + * W3C's note + */ +AbstractQueryTree.AbstractQueryTree = function() { +}; - AbstractQueryTree.AbstractQueryTree.prototype.parseQueryString = function(query_string) { +AbstractQueryTree.AbstractQueryTree.prototype.parseQueryString = function(query_string) { //noinspection UnnecessaryLocalVariableJS,UnnecessaryLocalVariableJS return SparqlParser.parser.parse(query_string); - }; +}; - AbstractQueryTree.AbstractQueryTree.prototype.parseExecutableUnit = function(executableUnit) { +AbstractQueryTree.AbstractQueryTree.prototype.parseExecutableUnit = function(executableUnit) { if(executableUnit.kind === 'select') { - return this.parseSelect(executableUnit); + return this.parseSelect(executableUnit); } else if(executableUnit.kind === 'ask') { - return this.parseSelect(executableUnit); + return this.parseSelect(executableUnit); } else if(executableUnit.kind === 'modify') { - return this.parseSelect(executableUnit); + return this.parseSelect(executableUnit); } else if(executableUnit.kind === 'construct') { - return this.parseSelect(executableUnit); + return this.parseSelect(executableUnit); } else if(executableUnit.kind === 'insertdata') { - return this.parseInsertData(executableUnit); + return this.parseInsertData(executableUnit); } else if(executableUnit.kind === 'deletedata') { - return this.parseInsertData(executableUnit); + return this.parseInsertData(executableUnit); } else if(executableUnit.kind === 'load') { - return executableUnit; + return executableUnit; } else if(executableUnit.kind === 'clear') { - return executableUnit; + return executableUnit; } else if(executableUnit.kind === 'drop') { - return executableUnit; + return executableUnit; } else if(executableUnit.kind === 'create') { - return executableUnit; + return executableUnit; } else { - throw new Error('unknown executable unit: ' + executableUnit.kind); + throw new Error('unknown executable unit: ' + executableUnit.kind); } - }; +}; - AbstractQueryTree.AbstractQueryTree.prototype.parseSelect = function(syntaxTree){ +AbstractQueryTree.AbstractQueryTree.prototype.parseSelect = function(syntaxTree){ if(syntaxTree == null) { - console.log("error parsing query"); - return null; + console.log("error parsing query"); + return null; } else { - var env = { freshCounter: 0 }; - syntaxTree.pattern = this.build(syntaxTree.pattern, env); - return syntaxTree; + var env = { freshCounter: 0 }; + syntaxTree.pattern = this.build(syntaxTree.pattern, env); + return syntaxTree; } - }; +}; - AbstractQueryTree.AbstractQueryTree.prototype.parseInsertData = function(syntaxTree){ +AbstractQueryTree.AbstractQueryTree.prototype.parseInsertData = function(syntaxTree){ if(syntaxTree == null) { - console.log("error parsing query"); - return null; + console.log("error parsing query"); + return null; } else { - return syntaxTree; + return syntaxTree; } - }; +}; - AbstractQueryTree.AbstractQueryTree.prototype.build = function(node, env) { +AbstractQueryTree.AbstractQueryTree.prototype.build = function(node, env) { if(node.token === 'groupgraphpattern') { - return this._buildGroupGraphPattern(node, env); + return this._buildGroupGraphPattern(node, env); } else if (node.token === 'basicgraphpattern') { - var bgp = { kind: 'BGP', - value: node.triplesContext }; - //console.log("pre1"); - bgp = AbstractQueryTree.translatePathExpressionsInBGP(bgp, env); - //console.log("translation"); - //console.log(sys.inspect(bgp,true,20)); - return bgp; + var bgp = { kind: 'BGP', + value: node.triplesContext }; + //console.log("pre1"); + bgp = AbstractQueryTree.translatePathExpressionsInBGP(bgp, env); + //console.log("translation"); + //console.log(sys.inspect(bgp,true,20)); + return bgp; } else if (node.token === 'graphunionpattern') { - var a = this.build(node.value[0],env); - var b = this.build(node.value[1],env); + var a = this.build(node.value[0],env); + var b = this.build(node.value[1],env); - return { kind: 'UNION', - value: [a,b] }; + return { kind: 'UNION', + value: [a,b] }; } else if(node.token === 'graphgraphpattern') { - var c = this.build(node.value, env); - return { kind: 'GRAPH', - value: c, - graph: node.graph }; + var c = this.build(node.value, env); + return { kind: 'GRAPH', + value: c, + graph: node.graph }; } else { - throw new Error("not supported token in query:"+node.token); + throw new Error("not supported token in query:"+node.token); } - }; +}; - AbstractQueryTree.translatePathExpressionsInBGP = function(bgp, env) { +AbstractQueryTree.translatePathExpressionsInBGP = function(bgp, env) { var pathExpression; var before = [], rest, bottomJoin; for(var i=0; i 0) { - bottomJoin = {kind: 'JOIN', - lvalue: {kind: 'BGP', value:before}, - rvalue: bgpTransformed}; - } else { - bottomJoin = bgpTransformed; - } - - - if(bgpTransformed.kind === 'ZERO_OR_MORE_PATH') { - if(bgpTransformed.y.token === 'var' && bgpTransformed.y.value.indexOf("fresh:")===0 && - bgpTransformed.x.token === 'var' && bgpTransformed.x.value.indexOf("fresh:")===0) { - //console.log("ADDING EXTRA PATTERN 1)"); - for(var j=0; j0) { - //console.log("(2a)") - var rvalueJoin = AbstractQueryTree.translatePathExpressionsInBGP({kind: 'BGP', value: rest}, env); - //console.log("got rvalue"); - if(optionalPattern != null) { - var optionals = before.concat([optionalPattern]).concat(rest); - return { kind: 'UNION', - value: [{ kind: 'JOIN', - lvalue: bottomJoin, - rvalue: rvalueJoin }, - {kind: 'BGP', - value: optionals}] }; - } else { - return { kind: 'JOIN', - lvalue: bottomJoin, - rvalue: rvalueJoin }; - } - } else { - //console.log("(2b)") - return bottomJoin; - } - - } else { - // @todo ???? - return bgpTransformed; - } - } else { - before.push(bgp.value[i]); - } + if(bgp.value[i].predicate && bgp.value[i].predicate.token === 'path') { + //console.log("FOUND A PATH"); + pathExpression = bgp.value[i]; + rest = bgp.value.slice(i+1); + var bgpTransformed = AbstractQueryTree.translatePathExpression(pathExpression, env); + var optionalPattern = null; + //console.log("BACK FROM TRANSFORMED"); + if(bgpTransformed.kind === 'BGP') { + before = before.concat(bgpTransformed.value); + } else if(bgpTransformed.kind === 'ZERO_OR_MORE_PATH' || bgpTransformed.kind === 'ONE_OR_MORE_PATH'){ + //console.log("BEFORE"); + //console.log(bgpTransformed); + + + if(before.length > 0) { + bottomJoin = {kind: 'JOIN', + lvalue: {kind: 'BGP', value:before}, + rvalue: bgpTransformed}; + } else { + bottomJoin = bgpTransformed; + } + + + if(bgpTransformed.kind === 'ZERO_OR_MORE_PATH') { + if(bgpTransformed.y.token === 'var' && bgpTransformed.y.value.indexOf("fresh:")===0 && + bgpTransformed.x.token === 'var' && bgpTransformed.x.value.indexOf("fresh:")===0) { + //console.log("ADDING EXTRA PATTERN 1)"); + for(var j=0; j0) { + //console.log("(2a)") + var rvalueJoin = AbstractQueryTree.translatePathExpressionsInBGP({kind: 'BGP', value: rest}, env); + //console.log("got rvalue"); + if(optionalPattern != null) { + var optionals = before.concat([optionalPattern]).concat(rest); + return { kind: 'UNION', + value: [{ kind: 'JOIN', + lvalue: bottomJoin, + rvalue: rvalueJoin }, + {kind: 'BGP', + value: optionals}] }; + } else { + return { kind: 'JOIN', + lvalue: bottomJoin, + rvalue: rvalueJoin }; + } + } else { + //console.log("(2b)") + return bottomJoin; + } + + } else { + // @todo ???? + return bgpTransformed; + } + } else { + before.push(bgp.value[i]); + } } //console.log("returning"); bgp.value = before; return bgp; - }; +}; - AbstractQueryTree.translatePathExpression = function(pathExpression, env) { +AbstractQueryTree.translatePathExpression = function(pathExpression, env) { // add support for different path patterns if(pathExpression.predicate.kind === 'element') { - // simple paths, maybe modified - if(pathExpression.predicate.modifier === '+') { - pathExpression.predicate.modifier = null; - var expandedPath = AbstractQueryTree.translatePathExpression(pathExpression, env); - return {kind: 'ONE_OR_MORE_PATH', - path: expandedPath, - x: pathExpression.subject, - y: pathExpression.object}; - } else if(pathExpression.predicate.modifier === '*') { - pathExpression.predicate.modifier = null; - var expandedPath = AbstractQueryTree.translatePathExpression(pathExpression, env); - return {kind: 'ZERO_OR_MORE_PATH', - path: expandedPath, - x: pathExpression.subject, - y: pathExpression.object}; - } else { - pathExpression.predicate = pathExpression.predicate.value; - return {kind: 'BGP', value: [pathExpression]}; - } + // simple paths, maybe modified + if(pathExpression.predicate.modifier === '+') { + pathExpression.predicate.modifier = null; + var expandedPath = AbstractQueryTree.translatePathExpression(pathExpression, env); + return {kind: 'ONE_OR_MORE_PATH', + path: expandedPath, + x: pathExpression.subject, + y: pathExpression.object}; + } else if(pathExpression.predicate.modifier === '*') { + pathExpression.predicate.modifier = null; + var expandedPath = AbstractQueryTree.translatePathExpression(pathExpression, env); + return {kind: 'ZERO_OR_MORE_PATH', + path: expandedPath, + x: pathExpression.subject, + y: pathExpression.object}; + } else { + pathExpression.predicate = pathExpression.predicate.value; + return {kind: 'BGP', value: [pathExpression]}; + } } else if(pathExpression.predicate.kind === 'sequence') { - var currentSubject = pathExpression.subject; - var lastObject = pathExpression.object; - var currentGraph = pathExpression.graph; - var nextObject, chain; - var restTriples = []; - for(var i=0; i< pathExpression.predicate.value.length; i++) { - if(i!=pathExpression.predicate.value.length-1) { - nextObject = { - token: "var", - value: "fresh:"+env.freshCounter - }; - env.freshCounter++; - } else { - nextObject = lastObject; - } - - // @todo - // what if the predicate is a path with - // '*'? same fresh va in subject and object?? - chain = { - subject: currentSubject, - predicate: pathExpression.predicate.value[i], - object: nextObject - }; - - if(currentGraph != null) - chain.graph = Utils.clone(currentGraph); - - restTriples.push(chain); - - if(i!=pathExpression.predicate.value.length-1) - currentSubject = Utils.clone(nextObject);; - } - var bgp = {kind: 'BGP', value: restTriples}; - //console.log("BEFORE (1):"); - //console.log(bgp); - //console.log("--------------"); - return AbstractQueryTree.translatePathExpressionsInBGP(bgp, env); - } - }; - - AbstractQueryTree.AbstractQueryTree.prototype._buildGroupGraphPattern = function(node, env) { + var currentSubject = pathExpression.subject; + var lastObject = pathExpression.object; + var currentGraph = pathExpression.graph; + var nextObject, chain; + var restTriples = []; + for(var i=0; i< pathExpression.predicate.value.length; i++) { + if(i!=pathExpression.predicate.value.length-1) { + nextObject = { + token: "var", + value: "fresh:"+env.freshCounter + }; + env.freshCounter++; + } else { + nextObject = lastObject; + } + + // @todo + // what if the predicate is a path with + // '*'? same fresh va in subject and object?? + chain = { + subject: currentSubject, + predicate: pathExpression.predicate.value[i], + object: nextObject + }; + + if(currentGraph != null) + chain.graph = Utils.clone(currentGraph); + + restTriples.push(chain); + + if(i!=pathExpression.predicate.value.length-1) + currentSubject = Utils.clone(nextObject);; + } + var bgp = {kind: 'BGP', value: restTriples}; + //console.log("BEFORE (1):"); + //console.log(bgp); + //console.log("--------------"); + return AbstractQueryTree.translatePathExpressionsInBGP(bgp, env); + } +}; + +AbstractQueryTree.AbstractQueryTree.prototype._buildGroupGraphPattern = function(node, env) { var f = (node.filters || []); var g = {kind: "EMPTY_PATTERN"}; for(var i=0; i rightmostFailuresPos) { - rightmostFailuresPos = pos; - rightmostFailuresExpected = []; - } - - rightmostFailuresExpected.push(failure); - } - - function parse_SPARQL() { - var result0; - - result0 = parse_Query(); - if (result0 === null) { - result0 = parse_Update(); - } - return result0; + return '"' + s + .replace(/\\/g, '\\\\') // backslash + .replace(/"/g, '\\"') // closing quote character + .replace(/\x08/g, '\\b') // backspace + .replace(/\t/g, '\\t') // horizontal tab + .replace(/\n/g, '\\n') // line feed + .replace(/\f/g, '\\f') // form feed + .replace(/\r/g, '\\r') // carriage return + .replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g, escape) + + '"'; + } + + var result = { + /* + * Parses the input with a generated parser. If the parsing is successfull, + * returns a value explicitly or implicitly specified by the grammar from + * which the parser was generated (see |PEG.buildParser|). If the parsing is + * unsuccessful, throws |PEG.parser.SyntaxError| describing the error. + */ + parse: function(input, startRule) { + var parseFunctions = { + "SPARQL": parse_SPARQL, + "Query": parse_Query, + "Prologue": parse_Prologue, + "BaseDecl": parse_BaseDecl, + "PrefixDecl": parse_PrefixDecl, + "SelectQuery": parse_SelectQuery, + "SubSelect": parse_SubSelect, + "SelectClause": parse_SelectClause, + "ConstructQuery": parse_ConstructQuery, + "DescribeQuery": parse_DescribeQuery, + "AskQuery": parse_AskQuery, + "DatasetClause": parse_DatasetClause, + "DefaultGraphClause": parse_DefaultGraphClause, + "NamedGraphClause": parse_NamedGraphClause, + "WhereClause": parse_WhereClause, + "SolutionModifier": parse_SolutionModifier, + "GroupClause": parse_GroupClause, + "GroupCondition": parse_GroupCondition, + "HavingClause": parse_HavingClause, + "OrderClause": parse_OrderClause, + "OrderCondition": parse_OrderCondition, + "LimitOffsetClauses": parse_LimitOffsetClauses, + "LimitClause": parse_LimitClause, + "OffsetClause": parse_OffsetClause, + "BindingsClause": parse_BindingsClause, + "BindingValue": parse_BindingValue, + "Update": parse_Update, + "Update1": parse_Update1, + "Load": parse_Load, + "Clear": parse_Clear, + "Drop": parse_Drop, + "Create": parse_Create, + "InsertData": parse_InsertData, + "DeleteData": parse_DeleteData, + "DeleteWhere": parse_DeleteWhere, + "Modify": parse_Modify, + "DeleteClause": parse_DeleteClause, + "InsertClause": parse_InsertClause, + "UsingClause": parse_UsingClause, + "GraphRef": parse_GraphRef, + "GraphRefAll": parse_GraphRefAll, + "QuadPattern": parse_QuadPattern, + "QuadData": parse_QuadData, + "Quads": parse_Quads, + "QuadsNotTriples": parse_QuadsNotTriples, + "TriplesTemplate": parse_TriplesTemplate, + "GroupGraphPattern": parse_GroupGraphPattern, + "GroupGraphPatternSub": parse_GroupGraphPatternSub, + "TriplesBlock": parse_TriplesBlock, + "GraphPatternNotTriples": parse_GraphPatternNotTriples, + "OptionalGraphPattern": parse_OptionalGraphPattern, + "GraphGraphPattern": parse_GraphGraphPattern, + "ServiceGraphPattern": parse_ServiceGraphPattern, + "MinusGraphPattern": parse_MinusGraphPattern, + "GroupOrUnionGraphPattern": parse_GroupOrUnionGraphPattern, + "Filter": parse_Filter, + "Constraint": parse_Constraint, + "FunctionCall": parse_FunctionCall, + "ArgList": parse_ArgList, + "ExpressionList": parse_ExpressionList, + "ConstructTemplate": parse_ConstructTemplate, + "ConstructTriples": parse_ConstructTriples, + "TriplesSameSubject": parse_TriplesSameSubject, + "PropertyListNotEmpty": parse_PropertyListNotEmpty, + "PropertyList": parse_PropertyList, + "ObjectList": parse_ObjectList, + "Verb": parse_Verb, + "TriplesSameSubjectPath": parse_TriplesSameSubjectPath, + "PropertyListNotEmptyPath": parse_PropertyListNotEmptyPath, + "PropertyListPath": parse_PropertyListPath, + "VerbPath": parse_VerbPath, + "PathAlternative": parse_PathAlternative, + "PathSequence": parse_PathSequence, + "PathElt": parse_PathElt, + "PathEltOrInverse": parse_PathEltOrInverse, + "PathMod": parse_PathMod, + "PathPrimary": parse_PathPrimary, + "PathNegatedPropertySet": parse_PathNegatedPropertySet, + "PathOneInPropertySet": parse_PathOneInPropertySet, + "TriplesNode": parse_TriplesNode, + "BlankNodePropertyList": parse_BlankNodePropertyList, + "Collection": parse_Collection, + "GraphNode": parse_GraphNode, + "VarOrTerm": parse_VarOrTerm, + "VarOrIRIref": parse_VarOrIRIref, + "Var": parse_Var, + "GraphTerm": parse_GraphTerm, + "ConditionalOrExpression": parse_ConditionalOrExpression, + "ConditionalAndExpression": parse_ConditionalAndExpression, + "RelationalExpression": parse_RelationalExpression, + "AdditiveExpression": parse_AdditiveExpression, + "MultiplicativeExpression": parse_MultiplicativeExpression, + "UnaryExpression": parse_UnaryExpression, + "PrimaryExpression": parse_PrimaryExpression, + "BrackettedExpression": parse_BrackettedExpression, + "BuiltInCall": parse_BuiltInCall, + "RegexExpression": parse_RegexExpression, + "ExistsFunc": parse_ExistsFunc, + "NotExistsFunc": parse_NotExistsFunc, + "Aggregate": parse_Aggregate, + "IRIrefOrFunction": parse_IRIrefOrFunction, + "RDFLiteral": parse_RDFLiteral, + "NumericLiteral": parse_NumericLiteral, + "NumericLiteralUnsigned": parse_NumericLiteralUnsigned, + "NumericLiteralPositive": parse_NumericLiteralPositive, + "NumericLiteralNegative": parse_NumericLiteralNegative, + "BooleanLiteral": parse_BooleanLiteral, + "String": parse_String, + "IRIref": parse_IRIref, + "PrefixedName": parse_PrefixedName, + "BlankNode": parse_BlankNode, + "IRI_REF": parse_IRI_REF, + "PNAME_NS": parse_PNAME_NS, + "PNAME_LN": parse_PNAME_LN, + "BLANK_NODE_LABEL": parse_BLANK_NODE_LABEL, + "VAR1": parse_VAR1, + "VAR2": parse_VAR2, + "LANGTAG": parse_LANGTAG, + "INTEGER": parse_INTEGER, + "DECIMAL": parse_DECIMAL, + "DOUBLE": parse_DOUBLE, + "INTEGER_POSITIVE": parse_INTEGER_POSITIVE, + "DECIMAL_POSITIVE": parse_DECIMAL_POSITIVE, + "DOUBLE_POSITIVE": parse_DOUBLE_POSITIVE, + "INTEGER_NEGATIVE": parse_INTEGER_NEGATIVE, + "DECIMAL_NEGATIVE": parse_DECIMAL_NEGATIVE, + "DOUBLE_NEGATIVE": parse_DOUBLE_NEGATIVE, + "EXPONENT": parse_EXPONENT, + "STRING_LITERAL1": parse_STRING_LITERAL1, + "STRING_LITERAL2": parse_STRING_LITERAL2, + "STRING_LITERAL_LONG1": parse_STRING_LITERAL_LONG1, + "STRING_LITERAL_LONG2": parse_STRING_LITERAL_LONG2, + "ECHAR": parse_ECHAR, + "NIL": parse_NIL, + "WS": parse_WS, + "COMMENT": parse_COMMENT, + "ANON": parse_ANON, + "PN_CHARS_BASE": parse_PN_CHARS_BASE, + "PN_CHARS_U": parse_PN_CHARS_U, + "VARNAME": parse_VARNAME, + "PN_CHARS": parse_PN_CHARS, + "PN_PREFIX": parse_PN_PREFIX, + "PN_LOCAL": parse_PN_LOCAL + }; + + if (startRule !== undefined) { + if (parseFunctions[startRule] === undefined) { + throw new Error("Invalid rule name: " + quote(startRule) + "."); } - - function parse_Query() { - var result0, result1; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = parse_Prologue(); - if (result0 !== null) { - result1 = parse_SelectQuery(); + } else { + startRule = "SPARQL"; + } + + var pos = 0; + var reportFailures = 0; + var rightmostFailuresPos = 0; + var rightmostFailuresExpected = []; + + function padLeft(input, padding, length) { + var result = input; + + var padLength = length - input.length; + for (var i = 0; i < padLength; i++) { + result = padding + result; + } + + return result; + } + + function escape(ch) { + var charCode = ch.charCodeAt(0); + var escapeChar; + var length; + + if (charCode <= 0xFF) { + escapeChar = 'x'; + length = 2; + } else { + escapeChar = 'u'; + length = 4; + } + + return '\\' + escapeChar + padLeft(charCode.toString(16).toUpperCase(), '0', length); + } + + function matchFailed(failure) { + if (pos < rightmostFailuresPos) { + return; + } + + if (pos > rightmostFailuresPos) { + rightmostFailuresPos = pos; + rightmostFailuresExpected = []; + } + + rightmostFailuresExpected.push(failure); + } + + function parse_SPARQL() { + var result0; + + result0 = parse_Query(); + if (result0 === null) { + result0 = parse_Update(); + } + return result0; + } + + function parse_Query() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = parse_Prologue(); + if (result0 !== null) { + result1 = parse_SelectQuery(); + if (result1 === null) { + result1 = parse_ConstructQuery(); if (result1 === null) { - result1 = parse_ConstructQuery(); + result1 = parse_DescribeQuery(); if (result1 === null) { - result1 = parse_DescribeQuery(); - if (result1 === null) { - result1 = parse_AskQuery(); - } + result1 = parse_AskQuery(); } } - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } + } + if (result1 !== null) { + result0 = [result0, result1]; } else { result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, p, q) { - return {token: 'query', - kind: 'query', - prologue: p, - units: [q]}; - })(pos0, result0[0], result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[2] Query"); - } - return result0; + } else { + result0 = null; + pos = pos1; } - - function parse_Prologue() { - var result0, result1, result2, result3; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = parse_BaseDecl(); - result0 = result0 !== null ? result0 : ""; - if (result0 !== null) { - result1 = []; + if (result0 !== null) { + result0 = (function(offset, p, q) { + return {token: 'query', + kind: 'query', + prologue: p, + units: [q]}; + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[2] Query"); + } + return result0; + } + + function parse_Prologue() { + var result0, result1, result2, result3; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = parse_BaseDecl(); + result0 = result0 !== null ? result0 : ""; + if (result0 !== null) { + result1 = []; + result2 = parse_WS(); + while (result2 !== null) { + result1.push(result2); result2 = parse_WS(); - while (result2 !== null) { - result1.push(result2); - result2 = parse_WS(); - } - if (result1 !== null) { - result2 = []; + } + if (result1 !== null) { + result2 = []; + result3 = parse_PrefixDecl(); + while (result3 !== null) { + result2.push(result3); result3 = parse_PrefixDecl(); - while (result3 !== null) { - result2.push(result3); - result3 = parse_PrefixDecl(); - } - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos1; - } + } + if (result2 !== null) { + result0 = [result0, result1, result2]; } else { result0 = null; pos = pos1; @@ -8171,72 +7602,72 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, b, pfx) { - return { token: 'prologue', - base: b, - prefixes: pfx } - })(pos0, result0[0], result0[2]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[3] Prologue"); - } - return result0; + } else { + result0 = null; + pos = pos1; } - - function parse_BaseDecl() { - var result0, result1, result2, result3; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = []; + if (result0 !== null) { + result0 = (function(offset, b, pfx) { + return { token: 'prologue', + base: b, + prefixes: pfx } + })(pos0, result0[0], result0[2]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[3] Prologue"); + } + return result0; + } + + function parse_BaseDecl() { + var result0, result1, result2, result3; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = []; + result1 = parse_WS(); + while (result1 !== null) { + result0.push(result1); result1 = parse_WS(); - while (result1 !== null) { - result0.push(result1); - result1 = parse_WS(); + } + if (result0 !== null) { + if (input.substr(pos, 4) === "BASE") { + result1 = "BASE"; + pos += 4; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\"BASE\""); + } } - if (result0 !== null) { - if (input.substr(pos, 4) === "BASE") { - result1 = "BASE"; + if (result1 === null) { + if (input.substr(pos, 4) === "base") { + result1 = "base"; pos += 4; } else { result1 = null; if (reportFailures === 0) { - matchFailed("\"BASE\""); - } - } - if (result1 === null) { - if (input.substr(pos, 4) === "base") { - result1 = "base"; - pos += 4; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("\"base\""); - } + matchFailed("\"base\""); } } - if (result1 !== null) { - result2 = []; + } + if (result1 !== null) { + result2 = []; + result3 = parse_WS(); + while (result3 !== null) { + result2.push(result3); result3 = parse_WS(); - while (result3 !== null) { - result2.push(result3); - result3 = parse_WS(); - } - if (result2 !== null) { - result3 = parse_IRI_REF(); - if (result3 !== null) { - result0 = [result0, result1, result2, result3]; - } else { - result0 = null; - pos = pos1; - } + } + if (result2 !== null) { + result3 = parse_IRI_REF(); + if (result3 !== null) { + result0 = [result0, result1, result2, result3]; } else { result0 = null; pos = pos1; @@ -8249,85 +7680,85 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, i) { + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, i) { registerDefaultPrefix(i); - + var base = {}; base.token = 'base'; base.value = i; - + return base; - })(pos0, result0[3]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[4] BaseDecl"); - } - return result0; - } - - function parse_PrefixDecl() { - var result0, result1, result2, result3, result4, result5; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = []; + })(pos0, result0[3]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[4] BaseDecl"); + } + return result0; + } + + function parse_PrefixDecl() { + var result0, result1, result2, result3, result4, result5; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = []; + result1 = parse_WS(); + while (result1 !== null) { + result0.push(result1); result1 = parse_WS(); - while (result1 !== null) { - result0.push(result1); - result1 = parse_WS(); + } + if (result0 !== null) { + if (input.substr(pos, 6) === "PREFIX") { + result1 = "PREFIX"; + pos += 6; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\"PREFIX\""); + } } - if (result0 !== null) { - if (input.substr(pos, 6) === "PREFIX") { - result1 = "PREFIX"; + if (result1 === null) { + if (input.substr(pos, 6) === "prefix") { + result1 = "prefix"; pos += 6; } else { result1 = null; if (reportFailures === 0) { - matchFailed("\"PREFIX\""); + matchFailed("\"prefix\""); } } - if (result1 === null) { - if (input.substr(pos, 6) === "prefix") { - result1 = "prefix"; - pos += 6; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("\"prefix\""); - } - } - } - if (result1 !== null) { - result2 = []; + } + if (result1 !== null) { + result2 = []; + result3 = parse_WS(); + while (result3 !== null) { + result2.push(result3); result3 = parse_WS(); - while (result3 !== null) { - result2.push(result3); - result3 = parse_WS(); - } - if (result2 !== null) { - result3 = parse_PNAME_NS(); - if (result3 !== null) { - result4 = []; + } + if (result2 !== null) { + result3 = parse_PNAME_NS(); + if (result3 !== null) { + result4 = []; + result5 = parse_WS(); + while (result5 !== null) { + result4.push(result5); result5 = parse_WS(); - while (result5 !== null) { - result4.push(result5); - result5 = parse_WS(); - } - if (result4 !== null) { - result5 = parse_IRI_REF(); - if (result5 !== null) { - result0 = [result0, result1, result2, result3, result4, result5]; - } else { - result0 = null; - pos = pos1; - } + } + if (result4 !== null) { + result5 = parse_IRI_REF(); + if (result5 !== null) { + result0 = [result0, result1, result2, result3, result4, result5]; } else { result0 = null; pos = pos1; @@ -8348,84 +7779,84 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, p, l) { - + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, p, l) { + registerPrefix(p,l); - + var prefix = {}; prefix.token = 'prefix'; prefix.prefix = p; prefix.local = l; - + return prefix; - })(pos0, result0[3], result0[5]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[5] PrefixDecl"); - } - return result0; - } - - function parse_SelectQuery() { - var result0, result1, result2, result3, result4, result5, result6, result7, result8; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = parse_SelectClause(); - if (result0 !== null) { - result1 = []; + })(pos0, result0[3], result0[5]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[5] PrefixDecl"); + } + return result0; + } + + function parse_SelectQuery() { + var result0, result1, result2, result3, result4, result5, result6, result7, result8; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = parse_SelectClause(); + if (result0 !== null) { + result1 = []; + result2 = parse_WS(); + while (result2 !== null) { + result1.push(result2); result2 = parse_WS(); - while (result2 !== null) { - result1.push(result2); - result2 = parse_WS(); - } - if (result1 !== null) { - result2 = []; + } + if (result1 !== null) { + result2 = []; + result3 = parse_DatasetClause(); + while (result3 !== null) { + result2.push(result3); result3 = parse_DatasetClause(); - while (result3 !== null) { - result2.push(result3); - result3 = parse_DatasetClause(); - } - if (result2 !== null) { - result3 = []; + } + if (result2 !== null) { + result3 = []; + result4 = parse_WS(); + while (result4 !== null) { + result3.push(result4); result4 = parse_WS(); - while (result4 !== null) { - result3.push(result4); - result4 = parse_WS(); - } - if (result3 !== null) { - result4 = parse_WhereClause(); - if (result4 !== null) { - result5 = []; + } + if (result3 !== null) { + result4 = parse_WhereClause(); + if (result4 !== null) { + result5 = []; + result6 = parse_WS(); + while (result6 !== null) { + result5.push(result6); result6 = parse_WS(); - while (result6 !== null) { - result5.push(result6); - result6 = parse_WS(); - } - if (result5 !== null) { - result6 = parse_SolutionModifier(); - if (result6 !== null) { - result7 = []; + } + if (result5 !== null) { + result6 = parse_SolutionModifier(); + if (result6 !== null) { + result7 = []; + result8 = parse_WS(); + while (result8 !== null) { + result7.push(result8); result8 = parse_WS(); - while (result8 !== null) { - result7.push(result8); - result8 = parse_WS(); - } - if (result7 !== null) { - result8 = parse_BindingsClause(); - if (result8 !== null) { - result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8]; - } else { - result0 = null; - pos = pos1; - } + } + if (result7 !== null) { + result8 = parse_BindingsClause(); + if (result8 !== null) { + result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8]; } else { result0 = null; pos = pos1; @@ -8458,27 +7889,31 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, s, gs, w, sm) { - + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, s, gs, w, sm) { + var dataset = {'named':[], 'implicit':[]}; for(var i=0; i0 && qs[0].length > 0) { - quads = quads.concat(qs[0][0].quadsContext); - - if( qs[0][2] != null && qs[0][2].triplesContext != null) { - for(var i=0; i 0) { - compactedSubpatterns.push({token: 'basicgraphpattern', - triplesContext: triplesContext}); - } - currentBasicGraphPatterns = []; - } - compactedSubpatterns.push(subpatterns[i]); - } else { - if(subpatterns[i].token === 'triplespattern') { - currentBasicGraphPatterns.push(subpatterns[i]); + if(subpatterns[i].token!='triplespattern' && subpatterns[i].token != 'filter') { + if(currentBasicGraphPatterns.length != 0 || currentFilters.length != 0) { + var triplesContext = []; + for(var j=0; j 0) { + compactedSubpatterns.push({token: 'basicgraphpattern', + triplesContext: triplesContext}); + } + currentBasicGraphPatterns = []; + } + compactedSubpatterns.push(subpatterns[i]); } else { - currentFilters.push(subpatterns[i]); + if(subpatterns[i].token === 'triplespattern') { + currentBasicGraphPatterns.push(subpatterns[i]); + } else { + currentFilters.push(subpatterns[i]); + } } - } } - + if(currentBasicGraphPatterns.length != 0 || currentFilters.length != 0) { - var triplesContext = []; - for(var j=0; j 0) { - compactedSubpatterns.push({token: 'basicgraphpattern', - triplesContext: triplesContext}); - } - } - - // if(compactedSubpatterns.length == 1) { - // compactedSubpatterns[0].filters = currentFilters; - // return compactedSubpatterns[0]; - // } else { - return { token: 'groupgraphpattern', - patterns: compactedSubpatterns, - filters: currentFilters } - // } - })(pos0, result0[0], result0[2]); + var triplesContext = []; + for(var j=0; j 0) { + compactedSubpatterns.push({token: 'basicgraphpattern', + triplesContext: triplesContext}); + } + } + + // if(compactedSubpatterns.length == 1) { + // compactedSubpatterns[0].filters = currentFilters; + // return compactedSubpatterns[0]; + // } else { + return { token: 'groupgraphpattern', + patterns: compactedSubpatterns, + filters: currentFilters } + // } + })(pos0, result0[0], result0[2]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[51] GroupGraphPatternSub"); + } + return result0; + } + + function parse_TriplesBlock() { + var result0, result1, result2, result3; + var pos0, pos1, pos2; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = parse_TriplesSameSubjectPath(); + if (result0 !== null) { + pos2 = pos; + result1 = []; + result2 = parse_WS(); + while (result2 !== null) { + result1.push(result2); + result2 = parse_WS(); } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[51] GroupGraphPatternSub"); - } - return result0; - } - - function parse_TriplesBlock() { - var result0, result1, result2, result3; - var pos0, pos1, pos2; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = parse_TriplesSameSubjectPath(); - if (result0 !== null) { - pos2 = pos; - result1 = []; - result2 = parse_WS(); - while (result2 !== null) { - result1.push(result2); - result2 = parse_WS(); - } - if (result1 !== null) { - if (input.charCodeAt(pos) === 46) { - result2 = "."; - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("\".\""); - } + if (result1 !== null) { + if (input.charCodeAt(pos) === 46) { + result2 = "."; + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\".\""); } - if (result2 !== null) { - result3 = parse_TriplesBlock(); - result3 = result3 !== null ? result3 : ""; - if (result3 !== null) { - result1 = [result1, result2, result3]; - } else { - result1 = null; - pos = pos2; - } + } + if (result2 !== null) { + result3 = parse_TriplesBlock(); + result3 = result3 !== null ? result3 : ""; + if (result3 !== null) { + result1 = [result1, result2, result3]; } else { result1 = null; pos = pos2; @@ -13443,119 +12874,119 @@ result1 = null; pos = pos2; } - result1 = result1 !== null ? result1 : ""; - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } + } else { + result1 = null; + pos = pos2; + } + result1 = result1 !== null ? result1 : ""; + if (result1 !== null) { + result0 = [result0, result1]; } else { result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, b, bs) { - var triples = b.triplesContext; - var toTest = null; - if(typeof(bs) === 'object') { - if(bs.length != null) { - if(bs[2].triplesContext!=null) { - triples = triples.concat(bs[2].triplesContext); - } - } - } - - return {token:'triplespattern', - triplesContext: triples} - })(pos0, result0[0], result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[54] TriplesBlock"); - } - return result0; + } else { + result0 = null; + pos = pos1; } - - function parse_GraphPatternNotTriples() { - var result0; - - reportFailures++; - result0 = parse_GroupOrUnionGraphPattern(); + if (result0 !== null) { + result0 = (function(offset, b, bs) { + var triples = b.triplesContext; + var toTest = null; + if(typeof(bs) === 'object') { + if(bs.length != null) { + if(bs[2].triplesContext!=null) { + triples = triples.concat(bs[2].triplesContext); + } + } + } + + return {token:'triplespattern', + triplesContext: triples} + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[54] TriplesBlock"); + } + return result0; + } + + function parse_GraphPatternNotTriples() { + var result0; + + reportFailures++; + result0 = parse_GroupOrUnionGraphPattern(); + if (result0 === null) { + result0 = parse_OptionalGraphPattern(); if (result0 === null) { - result0 = parse_OptionalGraphPattern(); + result0 = parse_MinusGraphPattern(); if (result0 === null) { - result0 = parse_MinusGraphPattern(); + result0 = parse_GraphGraphPattern(); if (result0 === null) { - result0 = parse_GraphGraphPattern(); + result0 = parse_ServiceGraphPattern(); if (result0 === null) { - result0 = parse_ServiceGraphPattern(); - if (result0 === null) { - result0 = parse_Filter(); - } + result0 = parse_Filter(); } } } } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[53] GraphPatternNotTriples"); - } - return result0; } - - function parse_OptionalGraphPattern() { - var result0, result1, result2, result3; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = []; + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[53] GraphPatternNotTriples"); + } + return result0; + } + + function parse_OptionalGraphPattern() { + var result0, result1, result2, result3; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = []; + result1 = parse_WS(); + while (result1 !== null) { + result0.push(result1); result1 = parse_WS(); - while (result1 !== null) { - result0.push(result1); - result1 = parse_WS(); + } + if (result0 !== null) { + if (input.substr(pos, 8) === "OPTIONAL") { + result1 = "OPTIONAL"; + pos += 8; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\"OPTIONAL\""); + } } - if (result0 !== null) { - if (input.substr(pos, 8) === "OPTIONAL") { - result1 = "OPTIONAL"; + if (result1 === null) { + if (input.substr(pos, 8) === "optional") { + result1 = "optional"; pos += 8; } else { result1 = null; if (reportFailures === 0) { - matchFailed("\"OPTIONAL\""); - } - } - if (result1 === null) { - if (input.substr(pos, 8) === "optional") { - result1 = "optional"; - pos += 8; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("\"optional\""); - } + matchFailed("\"optional\""); } } - if (result1 !== null) { - result2 = []; + } + if (result1 !== null) { + result2 = []; + result3 = parse_WS(); + while (result3 !== null) { + result2.push(result3); result3 = parse_WS(); - while (result3 !== null) { - result2.push(result3); - result3 = parse_WS(); - } - if (result2 !== null) { - result3 = parse_GroupGraphPattern(); - if (result3 !== null) { - result0 = [result0, result1, result2, result3]; - } else { - result0 = null; - pos = pos1; - } + } + if (result2 !== null) { + result3 = parse_GroupGraphPattern(); + if (result3 !== null) { + result0 = [result0, result1, result2, result3]; } else { result0 = null; pos = pos1; @@ -13568,80 +12999,80 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, v) { - return { token: 'optionalgraphpattern', - value: v } - })(pos0, result0[3]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[54] OptionalGraphPattern"); - } - return result0; + } else { + result0 = null; + pos = pos1; } - - function parse_GraphGraphPattern() { - var result0, result1, result2, result3, result4, result5; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = []; + if (result0 !== null) { + result0 = (function(offset, v) { + return { token: 'optionalgraphpattern', + value: v } + })(pos0, result0[3]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[54] OptionalGraphPattern"); + } + return result0; + } + + function parse_GraphGraphPattern() { + var result0, result1, result2, result3, result4, result5; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = []; + result1 = parse_WS(); + while (result1 !== null) { + result0.push(result1); result1 = parse_WS(); - while (result1 !== null) { - result0.push(result1); - result1 = parse_WS(); + } + if (result0 !== null) { + if (input.substr(pos, 5) === "GRAPH") { + result1 = "GRAPH"; + pos += 5; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\"GRAPH\""); + } } - if (result0 !== null) { - if (input.substr(pos, 5) === "GRAPH") { - result1 = "GRAPH"; + if (result1 === null) { + if (input.substr(pos, 5) === "graph") { + result1 = "graph"; pos += 5; } else { result1 = null; if (reportFailures === 0) { - matchFailed("\"GRAPH\""); - } - } - if (result1 === null) { - if (input.substr(pos, 5) === "graph") { - result1 = "graph"; - pos += 5; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("\"graph\""); - } + matchFailed("\"graph\""); } } - if (result1 !== null) { - result2 = []; + } + if (result1 !== null) { + result2 = []; + result3 = parse_WS(); + while (result3 !== null) { + result2.push(result3); result3 = parse_WS(); - while (result3 !== null) { - result2.push(result3); - result3 = parse_WS(); - } - if (result2 !== null) { - result3 = parse_VarOrIRIref(); - if (result3 !== null) { - result4 = []; + } + if (result2 !== null) { + result3 = parse_VarOrIRIref(); + if (result3 !== null) { + result4 = []; + result5 = parse_WS(); + while (result5 !== null) { + result4.push(result5); result5 = parse_WS(); - while (result5 !== null) { - result4.push(result5); - result5 = parse_WS(); - } - if (result4 !== null) { - result5 = parse_GroupGraphPattern(); - if (result5 !== null) { - result0 = [result0, result1, result2, result3, result4, result5]; - } else { - result0 = null; - pos = pos1; - } + } + if (result4 !== null) { + result5 = parse_GroupGraphPattern(); + if (result5 !== null) { + result0 = [result0, result1, result2, result3, result4, result5]; } else { result0 = null; pos = pos1; @@ -13662,57 +13093,57 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, g, gg) { + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, g, gg) { for(var i=0; i\""); } } if (result3 !== null) { @@ -17248,13 +16728,13 @@ result3 = parse_WS(); } if (result2 !== null) { - if (input.charCodeAt(pos) === 62) { - result3 = ">"; - pos++; + if (input.substr(pos, 2) === "<=") { + result3 = "<="; + pos += 2; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\">\""); + matchFailed("\"<=\""); } } if (result3 !== null) { @@ -17293,13 +16773,13 @@ result3 = parse_WS(); } if (result2 !== null) { - if (input.substr(pos, 2) === "<=") { - result3 = "<="; + if (input.substr(pos, 2) === ">=") { + result3 = ">="; pos += 2; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\"<=\""); + matchFailed("\">=\""); } } if (result3 !== null) { @@ -17338,26 +16818,62 @@ result3 = parse_WS(); } if (result2 !== null) { - if (input.substr(pos, 2) === ">=") { - result3 = ">="; - pos += 2; + if (input.charCodeAt(pos) === 73) { + result3 = "I"; + pos++; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\">=\""); + matchFailed("\"I\""); + } + } + if (result3 === null) { + if (input.charCodeAt(pos) === 105) { + result3 = "i"; + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\"i\""); + } } } if (result3 !== null) { - result4 = []; - result5 = parse_WS(); - while (result5 !== null) { - result4.push(result5); - result5 = parse_WS(); + if (input.charCodeAt(pos) === 78) { + result4 = "N"; + pos++; + } else { + result4 = null; + if (reportFailures === 0) { + matchFailed("\"N\""); + } + } + if (result4 === null) { + if (input.charCodeAt(pos) === 110) { + result4 = "n"; + pos++; + } else { + result4 = null; + if (reportFailures === 0) { + matchFailed("\"n\""); + } + } } if (result4 !== null) { - result5 = parse_AdditiveExpression(); + result5 = []; + result6 = parse_WS(); + while (result6 !== null) { + result5.push(result6); + result6 = parse_WS(); + } if (result5 !== null) { - result2 = [result2, result3, result4, result5]; + result6 = parse_ExpressionList(); + if (result6 !== null) { + result2 = [result2, result3, result4, result5, result6]; + } else { + result2 = null; + pos = pos2; + } } else { result2 = null; pos = pos2; @@ -17383,213 +16899,128 @@ result3 = parse_WS(); } if (result2 !== null) { - if (input.charCodeAt(pos) === 73) { - result3 = "I"; + if (input.charCodeAt(pos) === 78) { + result3 = "N"; pos++; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\"I\""); + matchFailed("\"N\""); } } if (result3 === null) { - if (input.charCodeAt(pos) === 105) { - result3 = "i"; + if (input.charCodeAt(pos) === 110) { + result3 = "n"; pos++; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\"i\""); + matchFailed("\"n\""); } } } if (result3 !== null) { - if (input.charCodeAt(pos) === 78) { - result4 = "N"; + if (input.charCodeAt(pos) === 79) { + result4 = "O"; pos++; } else { result4 = null; if (reportFailures === 0) { - matchFailed("\"N\""); + matchFailed("\"O\""); } } if (result4 === null) { - if (input.charCodeAt(pos) === 110) { - result4 = "n"; + if (input.charCodeAt(pos) === 111) { + result4 = "o"; pos++; } else { result4 = null; if (reportFailures === 0) { - matchFailed("\"n\""); + matchFailed("\"o\""); } } } if (result4 !== null) { - result5 = []; - result6 = parse_WS(); - while (result6 !== null) { - result5.push(result6); - result6 = parse_WS(); - } - if (result5 !== null) { - result6 = parse_ExpressionList(); - if (result6 !== null) { - result2 = [result2, result3, result4, result5, result6]; - } else { - result2 = null; - pos = pos2; - } - } else { - result2 = null; - pos = pos2; - } - } else { - result2 = null; - pos = pos2; - } - } else { - result2 = null; - pos = pos2; - } - } else { - result2 = null; - pos = pos2; - } - if (result2 === null) { - pos2 = pos; - result2 = []; - result3 = parse_WS(); - while (result3 !== null) { - result2.push(result3); - result3 = parse_WS(); - } - if (result2 !== null) { - if (input.charCodeAt(pos) === 78) { - result3 = "N"; - pos++; - } else { - result3 = null; - if (reportFailures === 0) { - matchFailed("\"N\""); - } - } - if (result3 === null) { - if (input.charCodeAt(pos) === 110) { - result3 = "n"; - pos++; - } else { - result3 = null; - if (reportFailures === 0) { - matchFailed("\"n\""); - } - } - } - if (result3 !== null) { - if (input.charCodeAt(pos) === 79) { - result4 = "O"; + if (input.charCodeAt(pos) === 84) { + result5 = "T"; pos++; } else { - result4 = null; + result5 = null; if (reportFailures === 0) { - matchFailed("\"O\""); + matchFailed("\"T\""); } } - if (result4 === null) { - if (input.charCodeAt(pos) === 111) { - result4 = "o"; + if (result5 === null) { + if (input.charCodeAt(pos) === 116) { + result5 = "t"; pos++; } else { - result4 = null; + result5 = null; if (reportFailures === 0) { - matchFailed("\"o\""); + matchFailed("\"t\""); } } } - if (result4 !== null) { - if (input.charCodeAt(pos) === 84) { - result5 = "T"; - pos++; - } else { - result5 = null; - if (reportFailures === 0) { - matchFailed("\"T\""); - } + if (result5 !== null) { + result6 = []; + result7 = parse_WS(); + while (result7 !== null) { + result6.push(result7); + result7 = parse_WS(); } - if (result5 === null) { - if (input.charCodeAt(pos) === 116) { - result5 = "t"; + if (result6 !== null) { + if (input.charCodeAt(pos) === 73) { + result7 = "I"; pos++; } else { - result5 = null; + result7 = null; if (reportFailures === 0) { - matchFailed("\"t\""); + matchFailed("\"I\""); } } - } - if (result5 !== null) { - result6 = []; - result7 = parse_WS(); - while (result7 !== null) { - result6.push(result7); - result7 = parse_WS(); - } - if (result6 !== null) { - if (input.charCodeAt(pos) === 73) { - result7 = "I"; + if (result7 === null) { + if (input.charCodeAt(pos) === 105) { + result7 = "i"; pos++; } else { result7 = null; if (reportFailures === 0) { - matchFailed("\"I\""); + matchFailed("\"i\""); } } - if (result7 === null) { - if (input.charCodeAt(pos) === 105) { - result7 = "i"; - pos++; - } else { - result7 = null; - if (reportFailures === 0) { - matchFailed("\"i\""); - } + } + if (result7 !== null) { + if (input.charCodeAt(pos) === 78) { + result8 = "N"; + pos++; + } else { + result8 = null; + if (reportFailures === 0) { + matchFailed("\"N\""); } } - if (result7 !== null) { - if (input.charCodeAt(pos) === 78) { - result8 = "N"; + if (result8 === null) { + if (input.charCodeAt(pos) === 110) { + result8 = "n"; pos++; } else { result8 = null; if (reportFailures === 0) { - matchFailed("\"N\""); + matchFailed("\"n\""); } } - if (result8 === null) { - if (input.charCodeAt(pos) === 110) { - result8 = "n"; - pos++; - } else { - result8 = null; - if (reportFailures === 0) { - matchFailed("\"n\""); - } - } - } - if (result8 !== null) { - result9 = []; + } + if (result8 !== null) { + result9 = []; + result10 = parse_WS(); + while (result10 !== null) { + result9.push(result10); result10 = parse_WS(); - while (result10 !== null) { - result9.push(result10); - result10 = parse_WS(); - } - if (result9 !== null) { - result10 = parse_ExpressionList(); - if (result10 !== null) { - result2 = [result2, result3, result4, result5, result6, result7, result8, result9, result10]; - } else { - result2 = null; - pos = pos2; - } + } + if (result9 !== null) { + result10 = parse_ExpressionList(); + if (result10 !== null) { + result2 = [result2, result3, result4, result5, result6, result7, result8, result9, result10]; } else { result2 = null; pos = pos2; @@ -17622,6 +17053,9 @@ result2 = null; pos = pos2; } + } else { + result2 = null; + pos = pos2; } } } @@ -17629,8 +17063,54 @@ } } } - while (result2 !== null) { - result1.push(result2); + } + while (result2 !== null) { + result1.push(result2); + pos2 = pos; + result2 = []; + result3 = parse_WS(); + while (result3 !== null) { + result2.push(result3); + result3 = parse_WS(); + } + if (result2 !== null) { + if (input.charCodeAt(pos) === 61) { + result3 = "="; + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\"=\""); + } + } + if (result3 !== null) { + result4 = []; + result5 = parse_WS(); + while (result5 !== null) { + result4.push(result5); + result5 = parse_WS(); + } + if (result4 !== null) { + result5 = parse_AdditiveExpression(); + if (result5 !== null) { + result2 = [result2, result3, result4, result5]; + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + } else { + result2 = null; + pos = pos2; + } + if (result2 === null) { pos2 = pos; result2 = []; result3 = parse_WS(); @@ -17639,13 +17119,13 @@ result3 = parse_WS(); } if (result2 !== null) { - if (input.charCodeAt(pos) === 61) { - result3 = "="; - pos++; + if (input.substr(pos, 2) === "!=") { + result3 = "!="; + pos += 2; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\"=\""); + matchFailed("\"!=\""); } } if (result3 !== null) { @@ -17684,13 +17164,13 @@ result3 = parse_WS(); } if (result2 !== null) { - if (input.substr(pos, 2) === "!=") { - result3 = "!="; - pos += 2; + if (input.charCodeAt(pos) === 60) { + result3 = "<"; + pos++; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\"!=\""); + matchFailed("\"<\""); } } if (result3 !== null) { @@ -17729,13 +17209,13 @@ result3 = parse_WS(); } if (result2 !== null) { - if (input.charCodeAt(pos) === 60) { - result3 = "<"; + if (input.charCodeAt(pos) === 62) { + result3 = ">"; pos++; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\"<\""); + matchFailed("\">\""); } } if (result3 !== null) { @@ -17774,13 +17254,13 @@ result3 = parse_WS(); } if (result2 !== null) { - if (input.charCodeAt(pos) === 62) { - result3 = ">"; - pos++; + if (input.substr(pos, 2) === "<=") { + result3 = "<="; + pos += 2; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\">\""); + matchFailed("\"<=\""); } } if (result3 !== null) { @@ -17819,13 +17299,13 @@ result3 = parse_WS(); } if (result2 !== null) { - if (input.substr(pos, 2) === "<=") { - result3 = "<="; + if (input.substr(pos, 2) === ">=") { + result3 = ">="; pos += 2; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\"<=\""); + matchFailed("\">=\""); } } if (result3 !== null) { @@ -17864,107 +17344,58 @@ result3 = parse_WS(); } if (result2 !== null) { - if (input.substr(pos, 2) === ">=") { - result3 = ">="; - pos += 2; + if (input.charCodeAt(pos) === 73) { + result3 = "I"; + pos++; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\">=\""); - } - } - if (result3 !== null) { - result4 = []; - result5 = parse_WS(); - while (result5 !== null) { - result4.push(result5); - result5 = parse_WS(); - } - if (result4 !== null) { - result5 = parse_AdditiveExpression(); - if (result5 !== null) { - result2 = [result2, result3, result4, result5]; - } else { - result2 = null; - pos = pos2; - } - } else { - result2 = null; - pos = pos2; + matchFailed("\"I\""); } - } else { - result2 = null; - pos = pos2; - } - } else { - result2 = null; - pos = pos2; - } - if (result2 === null) { - pos2 = pos; - result2 = []; - result3 = parse_WS(); - while (result3 !== null) { - result2.push(result3); - result3 = parse_WS(); } - if (result2 !== null) { - if (input.charCodeAt(pos) === 73) { - result3 = "I"; + if (result3 === null) { + if (input.charCodeAt(pos) === 105) { + result3 = "i"; pos++; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\"I\""); + matchFailed("\"i\""); } } - if (result3 === null) { - if (input.charCodeAt(pos) === 105) { - result3 = "i"; - pos++; - } else { - result3 = null; - if (reportFailures === 0) { - matchFailed("\"i\""); - } + } + if (result3 !== null) { + if (input.charCodeAt(pos) === 78) { + result4 = "N"; + pos++; + } else { + result4 = null; + if (reportFailures === 0) { + matchFailed("\"N\""); } } - if (result3 !== null) { - if (input.charCodeAt(pos) === 78) { - result4 = "N"; + if (result4 === null) { + if (input.charCodeAt(pos) === 110) { + result4 = "n"; pos++; } else { result4 = null; if (reportFailures === 0) { - matchFailed("\"N\""); - } - } - if (result4 === null) { - if (input.charCodeAt(pos) === 110) { - result4 = "n"; - pos++; - } else { - result4 = null; - if (reportFailures === 0) { - matchFailed("\"n\""); - } + matchFailed("\"n\""); } } - if (result4 !== null) { - result5 = []; + } + if (result4 !== null) { + result5 = []; + result6 = parse_WS(); + while (result6 !== null) { + result5.push(result6); result6 = parse_WS(); - while (result6 !== null) { - result5.push(result6); - result6 = parse_WS(); - } - if (result5 !== null) { - result6 = parse_ExpressionList(); - if (result6 !== null) { - result2 = [result2, result3, result4, result5, result6]; - } else { - result2 = null; - pos = pos2; - } + } + if (result5 !== null) { + result6 = parse_ExpressionList(); + if (result6 !== null) { + result2 = [result2, result3, result4, result5, result6]; } else { result2 = null; pos = pos2; @@ -17981,141 +17412,141 @@ result2 = null; pos = pos2; } - if (result2 === null) { - pos2 = pos; - result2 = []; + } else { + result2 = null; + pos = pos2; + } + if (result2 === null) { + pos2 = pos; + result2 = []; + result3 = parse_WS(); + while (result3 !== null) { + result2.push(result3); result3 = parse_WS(); - while (result3 !== null) { - result2.push(result3); - result3 = parse_WS(); + } + if (result2 !== null) { + if (input.charCodeAt(pos) === 78) { + result3 = "N"; + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("\"N\""); + } } - if (result2 !== null) { - if (input.charCodeAt(pos) === 78) { - result3 = "N"; + if (result3 === null) { + if (input.charCodeAt(pos) === 110) { + result3 = "n"; pos++; } else { result3 = null; if (reportFailures === 0) { - matchFailed("\"N\""); + matchFailed("\"n\""); + } + } + } + if (result3 !== null) { + if (input.charCodeAt(pos) === 79) { + result4 = "O"; + pos++; + } else { + result4 = null; + if (reportFailures === 0) { + matchFailed("\"O\""); } } - if (result3 === null) { - if (input.charCodeAt(pos) === 110) { - result3 = "n"; + if (result4 === null) { + if (input.charCodeAt(pos) === 111) { + result4 = "o"; pos++; } else { - result3 = null; + result4 = null; if (reportFailures === 0) { - matchFailed("\"n\""); + matchFailed("\"o\""); } } } - if (result3 !== null) { - if (input.charCodeAt(pos) === 79) { - result4 = "O"; + if (result4 !== null) { + if (input.charCodeAt(pos) === 84) { + result5 = "T"; pos++; } else { - result4 = null; + result5 = null; if (reportFailures === 0) { - matchFailed("\"O\""); + matchFailed("\"T\""); } } - if (result4 === null) { - if (input.charCodeAt(pos) === 111) { - result4 = "o"; + if (result5 === null) { + if (input.charCodeAt(pos) === 116) { + result5 = "t"; pos++; } else { - result4 = null; + result5 = null; if (reportFailures === 0) { - matchFailed("\"o\""); + matchFailed("\"t\""); } } } - if (result4 !== null) { - if (input.charCodeAt(pos) === 84) { - result5 = "T"; - pos++; - } else { - result5 = null; - if (reportFailures === 0) { - matchFailed("\"T\""); - } + if (result5 !== null) { + result6 = []; + result7 = parse_WS(); + while (result7 !== null) { + result6.push(result7); + result7 = parse_WS(); } - if (result5 === null) { - if (input.charCodeAt(pos) === 116) { - result5 = "t"; + if (result6 !== null) { + if (input.charCodeAt(pos) === 73) { + result7 = "I"; pos++; } else { - result5 = null; + result7 = null; if (reportFailures === 0) { - matchFailed("\"t\""); + matchFailed("\"I\""); } } - } - if (result5 !== null) { - result6 = []; - result7 = parse_WS(); - while (result7 !== null) { - result6.push(result7); - result7 = parse_WS(); - } - if (result6 !== null) { - if (input.charCodeAt(pos) === 73) { - result7 = "I"; + if (result7 === null) { + if (input.charCodeAt(pos) === 105) { + result7 = "i"; pos++; } else { result7 = null; if (reportFailures === 0) { - matchFailed("\"I\""); + matchFailed("\"i\""); } } - if (result7 === null) { - if (input.charCodeAt(pos) === 105) { - result7 = "i"; - pos++; - } else { - result7 = null; - if (reportFailures === 0) { - matchFailed("\"i\""); - } + } + if (result7 !== null) { + if (input.charCodeAt(pos) === 78) { + result8 = "N"; + pos++; + } else { + result8 = null; + if (reportFailures === 0) { + matchFailed("\"N\""); } } - if (result7 !== null) { - if (input.charCodeAt(pos) === 78) { - result8 = "N"; + if (result8 === null) { + if (input.charCodeAt(pos) === 110) { + result8 = "n"; pos++; } else { result8 = null; if (reportFailures === 0) { - matchFailed("\"N\""); - } - } - if (result8 === null) { - if (input.charCodeAt(pos) === 110) { - result8 = "n"; - pos++; - } else { - result8 = null; - if (reportFailures === 0) { - matchFailed("\"n\""); - } + matchFailed("\"n\""); } } - if (result8 !== null) { - result9 = []; + } + if (result8 !== null) { + result9 = []; + result10 = parse_WS(); + while (result10 !== null) { + result9.push(result10); result10 = parse_WS(); - while (result10 !== null) { - result9.push(result10); - result10 = parse_WS(); - } - if (result9 !== null) { - result10 = parse_ExpressionList(); - if (result10 !== null) { - result2 = [result2, result3, result4, result5, result6, result7, result8, result9, result10]; - } else { - result2 = null; - pos = pos2; - } + } + if (result9 !== null) { + result10 = parse_ExpressionList(); + if (result10 !== null) { + result2 = [result2, result3, result4, result5, result6, result7, result8, result9, result10]; } else { result2 = null; pos = pos2; @@ -18148,6 +17579,9 @@ result2 = null; pos = pos2; } + } else { + result2 = null; + pos = pos2; } } } @@ -18156,29 +17590,30 @@ } } } - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } + } + if (result1 !== null) { + result0 = [result0, result1]; } else { result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, op1, op2) { + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, op1, op2) { if(op2.length === 0) { - return op1; + return op1; } else if(op2[0][1] === 'i' || op2[0][1] === 'I' || op2[0][1] === 'n' || op2[0][1] === 'N'){ var exp = {}; - + if(op2[0][1] === 'i' || op2[0][1] === 'I') { var operator = "="; - exp.expressionType = "conditionalor" + exp.expressionType = "conditionalor" } else { var operator = "!="; - exp.expressionType = "conditionaland" + exp.expressionType = "conditionaland" } var lop = op1; var rops = [] @@ -18187,8 +17622,8 @@ rops = op2[0][opi].value; break; } - } - + } + exp.token = "expression"; exp.operands = []; for(var i=0; i 0) { + return {token:'literal', value:s.value, lang:e.slice(1), type:null} + } else { + if(typeof(e) === "object") { + e.shift(); // remove the '^^' char + return {token:'literal', value:s.value, lang:null, type:e[0] } } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"AVG\""); - } - } - if (result0 === null) { - if (input.substr(pos, 3) === "avg") { - result0 = "avg"; - pos += 3; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"avg\""); - } - } + return { token:'literal', value:s.value, lang:null, type:null } } - if (result0 !== null) { - result1 = []; - result2 = parse_WS(); - while (result2 !== null) { - result1.push(result2); - result2 = parse_WS(); - } - if (result1 !== null) { - if (input.charCodeAt(pos) === 40) { - result2 = "("; - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("\"(\""); - } - } - if (result2 !== null) { - result3 = []; - result4 = parse_WS(); - while (result4 !== null) { - result3.push(result4); - result4 = parse_WS(); - } - if (result3 !== null) { - if (input.substr(pos, 8) === "DISTINCT") { - result4 = "DISTINCT"; - pos += 8; - } else { - result4 = null; - if (reportFailures === 0) { - matchFailed("\"DISTINCT\""); - } - } - if (result4 === null) { - if (input.substr(pos, 8) === "distinct") { - result4 = "distinct"; - pos += 8; - } else { - result4 = null; - if (reportFailures === 0) { - matchFailed("\"distinct\""); - } - } - } - result4 = result4 !== null ? result4 : ""; - if (result4 !== null) { - result5 = []; - result6 = parse_WS(); - while (result6 !== null) { - result5.push(result6); - result6 = parse_WS(); - } - if (result5 !== null) { - result6 = parse_ConditionalOrExpression(); - if (result6 !== null) { - result7 = []; - result8 = parse_WS(); - while (result8 !== null) { - result7.push(result8); - result8 = parse_WS(); - } - if (result7 !== null) { - if (input.charCodeAt(pos) === 41) { - result8 = ")"; - pos++; - } else { - result8 = null; - if (reportFailures === 0) { - matchFailed("\")\""); - } - } - if (result8 !== null) { - result9 = []; - result10 = parse_WS(); - while (result10 !== null) { - result9.push(result10); - result10 = parse_WS(); - } - if (result9 !== null) { - result0 = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, d, e) { - var exp = {}; - exp.token = 'expression' - exp.expressionType = 'aggregate' - exp.aggregateType = 'avg' - exp.distinct = (d != "" ? 'DISTINCT' : d); - exp.expression = e - - return exp - - })(pos0, result0[4], result0[6]); - } - if (result0 === null) { - pos = pos0; - } - } } - } - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[110] Aggregate"); - } - return result0; + })(pos0, result0[0], result0[1]); } - - function parse_IRIrefOrFunction() { - var result0, result1; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = parse_IRIref(); - if (result0 !== null) { - result1 = parse_ArgList(); - result1 = result1 !== null ? result1 : ""; - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, i, args) { - var fcall = {}; - fcall.token = "expression"; - fcall.expressionType = 'irireforfunction'; - fcall.iriref = i; - fcall.args = args.value; - - return fcall; - })(pos0, result0[0], result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[117] IRIrefOrFunction"); - } - return result0; + if (result0 === null) { + pos = pos0; } - - function parse_RDFLiteral() { - var result0, result1, result2; - var pos0, pos1, pos2; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = parse_String(); - if (result0 !== null) { - result1 = parse_LANGTAG(); - if (result1 === null) { - pos2 = pos; - if (input.substr(pos, 2) === "^^") { - result1 = "^^"; - pos += 2; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("\"^^\""); - } - } - if (result1 !== null) { - result2 = parse_IRIref(); - if (result2 !== null) { - result1 = [result1, result2]; - } else { - result1 = null; - pos = pos2; - } - } else { - result1 = null; - pos = pos2; - } - } - result1 = result1 !== null ? result1 : ""; - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, s, e) { - if(typeof(e) === "string" && e.length > 0) { - return {token:'literal', value:s.value, lang:e.slice(1), type:null} - } else { - if(typeof(e) === "object") { - e.shift(); // remove the '^^' char - return {token:'literal', value:s.value, lang:null, type:e[0] } - } else { - return { token:'literal', value:s.value, lang:null, type:null } - } - } - })(pos0, result0[0], result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[112] RDFLiteral"); - } - return result0; + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[112] RDFLiteral"); } - - function parse_NumericLiteral() { - var result0; - - reportFailures++; - result0 = parse_NumericLiteralUnsigned(); + return result0; + } + + function parse_NumericLiteral() { + var result0; + + reportFailures++; + result0 = parse_NumericLiteralUnsigned(); + if (result0 === null) { + result0 = parse_NumericLiteralPositive(); if (result0 === null) { - result0 = parse_NumericLiteralPositive(); - if (result0 === null) { - result0 = parse_NumericLiteralNegative(); - } - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[113] NumericLiteral"); + result0 = parse_NumericLiteralNegative(); } - return result0; } - - function parse_NumericLiteralUnsigned() { - var result0; - - reportFailures++; - result0 = parse_DOUBLE(); + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[113] NumericLiteral"); + } + return result0; + } + + function parse_NumericLiteralUnsigned() { + var result0; + + reportFailures++; + result0 = parse_DOUBLE(); + if (result0 === null) { + result0 = parse_DECIMAL(); if (result0 === null) { - result0 = parse_DECIMAL(); - if (result0 === null) { - result0 = parse_INTEGER(); - } + result0 = parse_INTEGER(); } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[114] NumericLiteralUnsigned"); - } - return result0; } - - function parse_NumericLiteralPositive() { - var result0; - - reportFailures++; - result0 = parse_DOUBLE_POSITIVE(); + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[114] NumericLiteralUnsigned"); + } + return result0; + } + + function parse_NumericLiteralPositive() { + var result0; + + reportFailures++; + result0 = parse_DOUBLE_POSITIVE(); + if (result0 === null) { + result0 = parse_DECIMAL_POSITIVE(); if (result0 === null) { - result0 = parse_DECIMAL_POSITIVE(); - if (result0 === null) { - result0 = parse_INTEGER_POSITIVE(); - } - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[115] NumericLiteralPositive"); + result0 = parse_INTEGER_POSITIVE(); } - return result0; } - - function parse_NumericLiteralNegative() { - var result0; - - reportFailures++; - result0 = parse_DOUBLE_NEGATIVE(); + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[115] NumericLiteralPositive"); + } + return result0; + } + + function parse_NumericLiteralNegative() { + var result0; + + reportFailures++; + result0 = parse_DOUBLE_NEGATIVE(); + if (result0 === null) { + result0 = parse_DECIMAL_NEGATIVE(); if (result0 === null) { - result0 = parse_DECIMAL_NEGATIVE(); - if (result0 === null) { - result0 = parse_INTEGER_NEGATIVE(); - } + result0 = parse_INTEGER_NEGATIVE(); } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[116] NumericLiteralNegative"); + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[116] NumericLiteralNegative"); + } + return result0; + } + + function parse_BooleanLiteral() { + var result0; + var pos0; + + reportFailures++; + pos0 = pos; + if (input.substr(pos, 4) === "TRUE") { + result0 = "TRUE"; + pos += 4; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"TRUE\""); } - return result0; } - - function parse_BooleanLiteral() { - var result0; - var pos0; - - reportFailures++; - pos0 = pos; - if (input.substr(pos, 4) === "TRUE") { - result0 = "TRUE"; + if (result0 === null) { + if (input.substr(pos, 4) === "true") { + result0 = "true"; pos += 4; } else { result0 = null; if (reportFailures === 0) { - matchFailed("\"TRUE\""); - } - } - if (result0 === null) { - if (input.substr(pos, 4) === "true") { - result0 = "true"; - pos += 4; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"true\""); - } + matchFailed("\"true\""); } } - if (result0 !== null) { - result0 = (function(offset) { + } + if (result0 !== null) { + result0 = (function(offset) { var lit = {}; lit.token = "literal"; lit.lang = null; lit.type = "http://www.w3.org/2001/XMLSchema#boolean"; lit.value = true; return lit; - })(pos0); - } - if (result0 === null) { - pos = pos0; - } - if (result0 === null) { - pos0 = pos; - if (input.substr(pos, 5) === "FALSE") { - result0 = "FALSE"; - pos += 5; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"FALSE\""); - } - } - if (result0 === null) { - if (input.substr(pos, 5) === "false") { - result0 = "false"; - pos += 5; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"false\""); - } - } - } - if (result0 !== null) { - result0 = (function(offset) { - var lit = {}; - lit.token = "literal"; - lit.lang = null; - lit.type = "http://www.w3.org/2001/XMLSchema#boolean"; - lit.value = false; - return lit; - })(pos0); - } - if (result0 === null) { - pos = pos0; - } - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[117] BooleanLiteral"); - } - return result0; - } - - function parse_String() { - var result0; - var pos0; - - reportFailures++; - pos0 = pos; - result0 = parse_STRING_LITERAL_LONG1(); - if (result0 !== null) { - result0 = (function(offset, s) { return {token:'string', value:s} })(pos0, result0); - } - if (result0 === null) { - pos = pos0; - } - if (result0 === null) { - pos0 = pos; - result0 = parse_STRING_LITERAL_LONG2(); - if (result0 !== null) { - result0 = (function(offset, s) { return {token:'string', value:s} })(pos0, result0); - } - if (result0 === null) { - pos = pos0; - } - if (result0 === null) { - pos0 = pos; - result0 = parse_STRING_LITERAL1(); - if (result0 !== null) { - result0 = (function(offset, s) { return {token:'string', value:s} })(pos0, result0); - } - if (result0 === null) { - pos = pos0; - } - if (result0 === null) { - pos0 = pos; - result0 = parse_STRING_LITERAL2(); - if (result0 !== null) { - result0 = (function(offset, s) { return {token:'string', value:s} })(pos0, result0); - } - if (result0 === null) { - pos = pos0; - } - } - } - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[118] String"); - } - return result0; - } - - function parse_IRIref() { - var result0; - var pos0; - - reportFailures++; - pos0 = pos; - result0 = parse_IRI_REF(); - if (result0 !== null) { - result0 = (function(offset, iri) { return {token: 'uri', prefix:null, suffix:null, value:iri} })(pos0, result0); - } - if (result0 === null) { - pos = pos0; - } - if (result0 === null) { - pos0 = pos; - result0 = parse_PrefixedName(); - if (result0 !== null) { - result0 = (function(offset, p) { return p })(pos0, result0); - } - if (result0 === null) { - pos = pos0; - } - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[119] IRIref"); - } - return result0; - } - - function parse_PrefixedName() { - var result0; - var pos0; - - reportFailures++; - pos0 = pos; - result0 = parse_PNAME_LN(); - if (result0 !== null) { - result0 = (function(offset, p) { return {token: 'uri', prefix:p[0], suffix:p[1], value:null } })(pos0, result0); - } - if (result0 === null) { - pos = pos0; - } - if (result0 === null) { - pos0 = pos; - result0 = parse_PNAME_NS(); - if (result0 !== null) { - result0 = (function(offset, p) { return {token: 'uri', prefix:p, suffix:'', value:null } })(pos0, result0); - } - if (result0 === null) { - pos = pos0; - } - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[120] PrefixedName"); - } - return result0; - } - - function parse_BlankNode() { - var result0; - var pos0; - - reportFailures++; - pos0 = pos; - result0 = parse_BLANK_NODE_LABEL(); - if (result0 !== null) { - result0 = (function(offset, l) { return {token:'blank', value:l}})(pos0, result0); - } - if (result0 === null) { - pos = pos0; - } - if (result0 === null) { - pos0 = pos; - result0 = parse_ANON(); - if (result0 !== null) { - result0 = (function(offset) { GlobalBlankNodeCounter++; return {token:'blank', value:'_:'+GlobalBlankNodeCounter} })(pos0); - } - if (result0 === null) { - pos = pos0; - } - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[121] BlankNode"); - } - return result0; - } - - function parse_IRI_REF() { - var result0, result1, result2; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 60) { - result0 = "<"; - pos++; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"<\""); - } - } - if (result0 !== null) { - result1 = []; - if (/^[^<>"{}|^`\\]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[^<>\"{}|^`\\\\]"); - } - } - while (result2 !== null) { - result1.push(result2); - if (/^[^<>"{}|^`\\]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[^<>\"{}|^`\\\\]"); - } - } - } - if (result1 !== null) { - if (input.charCodeAt(pos) === 62) { - result2 = ">"; - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("\">\""); - } - } - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, iri_ref) { return iri_ref.join('') })(pos0, result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[122] IRI_REF"); - } - return result0; - } - - function parse_PNAME_NS() { - var result0, result1; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = parse_PN_PREFIX(); - result0 = result0 !== null ? result0 : ""; - if (result0 !== null) { - if (input.charCodeAt(pos) === 58) { - result1 = ":"; - pos++; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("\":\""); - } - } - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, p) { return p })(pos0, result0[0]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[123] PNAME_NS"); - } - return result0; - } - - function parse_PNAME_LN() { - var result0, result1; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = parse_PNAME_NS(); - if (result0 !== null) { - result1 = parse_PN_LOCAL(); - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, p, s) { return [p, s] })(pos0, result0[0], result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[124] PNAME_LN"); - } - return result0; - } - - function parse_BLANK_NODE_LABEL() { - var result0, result1; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.substr(pos, 2) === "_:") { - result0 = "_:"; - pos += 2; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"_:\""); - } - } - if (result0 !== null) { - result1 = parse_PN_LOCAL(); - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, l) { return l })(pos0, result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[125] BLANK_NODE_LABEL"); - } - return result0; - } - - function parse_VAR1() { - var result0, result1; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 63) { - result0 = "?"; - pos++; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"?\""); - } - } - if (result0 !== null) { - result1 = parse_VARNAME(); - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, v) { return v })(pos0, result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[126] VAR1"); - } - return result0; - } - - function parse_VAR2() { - var result0, result1; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 36) { - result0 = "$"; - pos++; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"$\""); - } - } - if (result0 !== null) { - result1 = parse_VARNAME(); - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, v) { return v })(pos0, result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[127] VAR2"); - } - return result0; - } - - function parse_LANGTAG() { - var result0, result1, result2, result3, result4, result5; - var pos0, pos1, pos2; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 64) { - result0 = "@"; - pos++; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"@\""); - } - } - if (result0 !== null) { - if (/^[a-zA-Z]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[a-zA-Z]"); - } - } - if (result2 !== null) { - result1 = []; - while (result2 !== null) { - result1.push(result2); - if (/^[a-zA-Z]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[a-zA-Z]"); - } - } - } - } else { - result1 = null; - } - if (result1 !== null) { - result2 = []; - pos2 = pos; - if (input.charCodeAt(pos) === 45) { - result3 = "-"; - pos++; - } else { - result3 = null; - if (reportFailures === 0) { - matchFailed("\"-\""); - } - } - if (result3 !== null) { - if (/^[a-zA-Z0-9]/.test(input.charAt(pos))) { - result5 = input.charAt(pos); - pos++; - } else { - result5 = null; - if (reportFailures === 0) { - matchFailed("[a-zA-Z0-9]"); - } - } - if (result5 !== null) { - result4 = []; - while (result5 !== null) { - result4.push(result5); - if (/^[a-zA-Z0-9]/.test(input.charAt(pos))) { - result5 = input.charAt(pos); - pos++; - } else { - result5 = null; - if (reportFailures === 0) { - matchFailed("[a-zA-Z0-9]"); - } - } - } - } else { - result4 = null; - } - if (result4 !== null) { - result3 = [result3, result4]; - } else { - result3 = null; - pos = pos2; - } - } else { - result3 = null; - pos = pos2; - } - while (result3 !== null) { - result2.push(result3); - pos2 = pos; - if (input.charCodeAt(pos) === 45) { - result3 = "-"; - pos++; - } else { - result3 = null; - if (reportFailures === 0) { - matchFailed("\"-\""); - } - } - if (result3 !== null) { - if (/^[a-zA-Z0-9]/.test(input.charAt(pos))) { - result5 = input.charAt(pos); - pos++; - } else { - result5 = null; - if (reportFailures === 0) { - matchFailed("[a-zA-Z0-9]"); - } - } - if (result5 !== null) { - result4 = []; - while (result5 !== null) { - result4.push(result5); - if (/^[a-zA-Z0-9]/.test(input.charAt(pos))) { - result5 = input.charAt(pos); - pos++; - } else { - result5 = null; - if (reportFailures === 0) { - matchFailed("[a-zA-Z0-9]"); - } - } - } - } else { - result4 = null; - } - if (result4 !== null) { - result3 = [result3, result4]; - } else { - result3 = null; - pos = pos2; - } - } else { - result3 = null; - pos = pos2; - } - } - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, a, b) { - - if(b.length===0) { - return ("@"+a.join('')).toLowerCase(); - } else { - return ("@"+a.join('')+"-"+b[0][1].join('')).toLowerCase(); - } - })(pos0, result0[1], result0[2]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[128] LANGTAG"); - } - return result0; + })(pos0); } - - function parse_INTEGER() { - var result0, result1; - var pos0; - - reportFailures++; - pos0 = pos; - if (/^[0-9]/.test(input.charAt(pos))) { - result1 = input.charAt(pos); - pos++; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } - } - if (result1 !== null) { - result0 = []; - while (result1 !== null) { - result0.push(result1); - if (/^[0-9]/.test(input.charAt(pos))) { - result1 = input.charAt(pos); - pos++; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } - } - } - } else { - result0 = null; - } - if (result0 !== null) { - result0 = (function(offset, d) { - var lit = {}; - lit.token = "literal"; - lit.lang = null; - lit.type = "http://www.w3.org/2001/XMLSchema#integer"; - lit.value = flattenString(d); - return lit; - })(pos0, result0); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[129] INTEGER"); - } - return result0; + if (result0 === null) { + pos = pos0; } - - function parse_DECIMAL() { - var result0, result1, result2, result3; - var pos0, pos1; - - reportFailures++; + if (result0 === null) { pos0 = pos; - pos1 = pos; - if (/^[0-9]/.test(input.charAt(pos))) { - result1 = input.charAt(pos); - pos++; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } - } - if (result1 !== null) { - result0 = []; - while (result1 !== null) { - result0.push(result1); - if (/^[0-9]/.test(input.charAt(pos))) { - result1 = input.charAt(pos); - pos++; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } - } - } - } else { - result0 = null; - } - if (result0 !== null) { - if (input.charCodeAt(pos) === 46) { - result1 = "."; - pos++; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("\".\""); - } - } - if (result1 !== null) { - result2 = []; - if (/^[0-9]/.test(input.charAt(pos))) { - result3 = input.charAt(pos); - pos++; - } else { - result3 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } - } - while (result3 !== null) { - result2.push(result3); - if (/^[0-9]/.test(input.charAt(pos))) { - result3 = input.charAt(pos); - pos++; - } else { - result3 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } - } - } - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } + if (input.substr(pos, 5) === "FALSE") { + result0 = "FALSE"; + pos += 5; } else { result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, a, b, c) { - - var lit = {}; - lit.token = "literal"; - lit.lang = null; - lit.type = "http://www.w3.org/2001/XMLSchema#decimal"; - lit.value = flattenString([a,b,c]); - return lit; - })(pos0, result0[0], result0[1], result0[2]); - } - if (result0 === null) { - pos = pos0; + if (reportFailures === 0) { + matchFailed("\"FALSE\""); + } } if (result0 === null) { - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 46) { - result0 = "."; - pos++; + if (input.substr(pos, 5) === "false") { + result0 = "false"; + pos += 5; } else { result0 = null; if (reportFailures === 0) { - matchFailed("\".\""); - } - } - if (result0 !== null) { - if (/^[0-9]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } - } - if (result2 !== null) { - result1 = []; - while (result2 !== null) { - result1.push(result2); - if (/^[0-9]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } - } - } - } else { - result1 = null; - } - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; + matchFailed("\"false\""); } - } else { - result0 = null; - pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, a, b) { + } + if (result0 !== null) { + result0 = (function(offset) { var lit = {}; lit.token = "literal"; lit.lang = null; - lit.type = "http://www.w3.org/2001/XMLSchema#decimal"; - lit.value = flattenString([a,b]); + lit.type = "http://www.w3.org/2001/XMLSchema#boolean"; + lit.value = false; return lit; - })(pos0, result0[0], result0[1]); + })(pos0); + } + if (result0 === null) { + pos = pos0; + } + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[117] BooleanLiteral"); + } + return result0; + } + + function parse_String() { + var result0; + var pos0; + + reportFailures++; + pos0 = pos; + result0 = parse_STRING_LITERAL_LONG1(); + if (result0 !== null) { + result0 = (function(offset, s) { return {token:'string', value:s} })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + result0 = parse_STRING_LITERAL_LONG2(); + if (result0 !== null) { + result0 = (function(offset, s) { return {token:'string', value:s} })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + result0 = parse_STRING_LITERAL1(); + if (result0 !== null) { + result0 = (function(offset, s) { return {token:'string', value:s} })(pos0, result0); } if (result0 === null) { pos = pos0; } + if (result0 === null) { + pos0 = pos; + result0 = parse_STRING_LITERAL2(); + if (result0 !== null) { + result0 = (function(offset, s) { return {token:'string', value:s} })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + } + } + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[118] String"); + } + return result0; + } + + function parse_IRIref() { + var result0; + var pos0; + + reportFailures++; + pos0 = pos; + result0 = parse_IRI_REF(); + if (result0 !== null) { + result0 = (function(offset, iri) { return {token: 'uri', prefix:null, suffix:null, value:iri} })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + result0 = parse_PrefixedName(); + if (result0 !== null) { + result0 = (function(offset, p) { return p })(pos0, result0); } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[130] DECIMAL"); + if (result0 === null) { + pos = pos0; } - return result0; } - - function parse_DOUBLE() { - var result0, result1, result2, result3; - var pos0, pos1; - - reportFailures++; + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[119] IRIref"); + } + return result0; + } + + function parse_PrefixedName() { + var result0; + var pos0; + + reportFailures++; + pos0 = pos; + result0 = parse_PNAME_LN(); + if (result0 !== null) { + result0 = (function(offset, p) { return {token: 'uri', prefix:p[0], suffix:p[1], value:null } })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { pos0 = pos; - pos1 = pos; - if (/^[0-9]/.test(input.charAt(pos))) { - result1 = input.charAt(pos); + result0 = parse_PNAME_NS(); + if (result0 !== null) { + result0 = (function(offset, p) { return {token: 'uri', prefix:p, suffix:'', value:null } })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[120] PrefixedName"); + } + return result0; + } + + function parse_BlankNode() { + var result0; + var pos0; + + reportFailures++; + pos0 = pos; + result0 = parse_BLANK_NODE_LABEL(); + if (result0 !== null) { + result0 = (function(offset, l) { return {token:'blank', value:l}})(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { + pos0 = pos; + result0 = parse_ANON(); + if (result0 !== null) { + result0 = (function(offset) { GlobalBlankNodeCounter++; return {token:'blank', value:'_:'+GlobalBlankNodeCounter} })(pos0); + } + if (result0 === null) { + pos = pos0; + } + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[121] BlankNode"); + } + return result0; + } + + function parse_IRI_REF() { + var result0, result1, result2; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 60) { + result0 = "<"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"<\""); + } + } + if (result0 !== null) { + result1 = []; + if (/^[^<>"{}|^`\\]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); pos++; } else { - result1 = null; + result2 = null; if (reportFailures === 0) { - matchFailed("[0-9]"); + matchFailed("[^<>\"{}|^`\\\\]"); } } - if (result1 !== null) { - result0 = []; - while (result1 !== null) { - result0.push(result1); - if (/^[0-9]/.test(input.charAt(pos))) { - result1 = input.charAt(pos); - pos++; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } + while (result2 !== null) { + result1.push(result2); + if (/^[^<>"{}|^`\\]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[^<>\"{}|^`\\\\]"); } } - } else { - result0 = null; } - if (result0 !== null) { - if (input.charCodeAt(pos) === 46) { - result1 = "."; + if (result1 !== null) { + if (input.charCodeAt(pos) === 62) { + result2 = ">"; pos++; } else { - result1 = null; + result2 = null; if (reportFailures === 0) { - matchFailed("\".\""); + matchFailed("\">\""); } } - if (result1 !== null) { - result2 = []; - if (/^[0-9]/.test(input.charAt(pos))) { - result3 = input.charAt(pos); - pos++; - } else { - result3 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } - } - while (result3 !== null) { - result2.push(result3); - if (/^[0-9]/.test(input.charAt(pos))) { - result3 = input.charAt(pos); - pos++; - } else { - result3 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } - } - } - if (result2 !== null) { - result3 = parse_EXPONENT(); - if (result3 !== null) { - result0 = [result0, result1, result2, result3]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } + if (result2 !== null) { + result0 = [result0, result1, result2]; } else { result0 = null; pos = pos1; @@ -23591,170 +22333,517 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, a, b, c, e) { - var lit = {}; - lit.token = "literal"; - lit.lang = null; - lit.type = "http://www.w3.org/2001/XMLSchema#double"; - lit.value = flattenString([a,b,c,e]); - return lit; - })(pos0, result0[0], result0[1], result0[2], result0[3]); + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, iri_ref) { return iri_ref.join('') })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[122] IRI_REF"); + } + return result0; + } + + function parse_PNAME_NS() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = parse_PN_PREFIX(); + result0 = result0 !== null ? result0 : ""; + if (result0 !== null) { + if (input.charCodeAt(pos) === 58) { + result1 = ":"; + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("\":\""); + } } - if (result0 === null) { - pos = pos0; + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, p) { return p })(pos0, result0[0]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[123] PNAME_NS"); + } + return result0; + } + + function parse_PNAME_LN() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = parse_PNAME_NS(); + if (result0 !== null) { + result1 = parse_PN_LOCAL(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, p, s) { return [p, s] })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[124] PNAME_LN"); + } + return result0; + } + + function parse_BLANK_NODE_LABEL() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.substr(pos, 2) === "_:") { + result0 = "_:"; + pos += 2; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"_:\""); + } + } + if (result0 !== null) { + result1 = parse_PN_LOCAL(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, l) { return l })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[125] BLANK_NODE_LABEL"); + } + return result0; + } + + function parse_VAR1() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 63) { + result0 = "?"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"?\""); + } + } + if (result0 !== null) { + result1 = parse_VARNAME(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, v) { return v })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[126] VAR1"); + } + return result0; + } + + function parse_VAR2() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 36) { + result0 = "$"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"$\""); + } + } + if (result0 !== null) { + result1 = parse_VARNAME(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, v) { return v })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[127] VAR2"); + } + return result0; + } + + function parse_LANGTAG() { + var result0, result1, result2, result3, result4, result5; + var pos0, pos1, pos2; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 64) { + result0 = "@"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"@\""); + } + } + if (result0 !== null) { + if (/^[a-zA-Z]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z]"); + } + } + if (result2 !== null) { + result1 = []; + while (result2 !== null) { + result1.push(result2); + if (/^[a-zA-Z]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z]"); + } + } + } + } else { + result1 = null; } - if (result0 === null) { - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 46) { - result0 = "."; + if (result1 !== null) { + result2 = []; + pos2 = pos; + if (input.charCodeAt(pos) === 45) { + result3 = "-"; pos++; } else { - result0 = null; + result3 = null; if (reportFailures === 0) { - matchFailed("\".\""); + matchFailed("\"-\""); } } - if (result0 !== null) { - if (/^[0-9]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); + if (result3 !== null) { + if (/^[a-zA-Z0-9]/.test(input.charAt(pos))) { + result5 = input.charAt(pos); pos++; } else { - result2 = null; + result5 = null; if (reportFailures === 0) { - matchFailed("[0-9]"); + matchFailed("[a-zA-Z0-9]"); } } - if (result2 !== null) { - result1 = []; - while (result2 !== null) { - result1.push(result2); - if (/^[0-9]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); + if (result5 !== null) { + result4 = []; + while (result5 !== null) { + result4.push(result5); + if (/^[a-zA-Z0-9]/.test(input.charAt(pos))) { + result5 = input.charAt(pos); pos++; } else { - result2 = null; + result5 = null; if (reportFailures === 0) { - matchFailed("[0-9]"); + matchFailed("[a-zA-Z0-9]"); } } } } else { - result1 = null; + result4 = null; } - if (result1 !== null) { - result2 = parse_EXPONENT(); - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos1; - } + if (result4 !== null) { + result3 = [result3, result4]; } else { - result0 = null; - pos = pos1; + result3 = null; + pos = pos2; } } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, a, b, c) { - var lit = {}; - lit.token = "literal"; - lit.lang = null; - lit.type = "http://www.w3.org/2001/XMLSchema#double"; - lit.value = flattenString([a,b,c]); - return lit; - })(pos0, result0[0], result0[1], result0[2]); - } - if (result0 === null) { - pos = pos0; + result3 = null; + pos = pos2; } - if (result0 === null) { - pos0 = pos; - pos1 = pos; - if (/^[0-9]/.test(input.charAt(pos))) { - result1 = input.charAt(pos); + while (result3 !== null) { + result2.push(result3); + pos2 = pos; + if (input.charCodeAt(pos) === 45) { + result3 = "-"; pos++; } else { - result1 = null; + result3 = null; if (reportFailures === 0) { - matchFailed("[0-9]"); + matchFailed("\"-\""); } } - if (result1 !== null) { - result0 = []; - while (result1 !== null) { - result0.push(result1); - if (/^[0-9]/.test(input.charAt(pos))) { - result1 = input.charAt(pos); - pos++; - } else { - result1 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); + if (result3 !== null) { + if (/^[a-zA-Z0-9]/.test(input.charAt(pos))) { + result5 = input.charAt(pos); + pos++; + } else { + result5 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z0-9]"); + } + } + if (result5 !== null) { + result4 = []; + while (result5 !== null) { + result4.push(result5); + if (/^[a-zA-Z0-9]/.test(input.charAt(pos))) { + result5 = input.charAt(pos); + pos++; + } else { + result5 = null; + if (reportFailures === 0) { + matchFailed("[a-zA-Z0-9]"); + } } } + } else { + result4 = null; } - } else { - result0 = null; - } - if (result0 !== null) { - result1 = parse_EXPONENT(); - if (result1 !== null) { - result0 = [result0, result1]; + if (result4 !== null) { + result3 = [result3, result4]; } else { - result0 = null; - pos = pos1; + result3 = null; + pos = pos2; } } else { - result0 = null; - pos = pos1; + result3 = null; + pos = pos2; } - if (result0 !== null) { - result0 = (function(offset, a, b) { - var lit = {}; - lit.token = "literal"; - lit.lang = null; - lit.type = "http://www.w3.org/2001/XMLSchema#double"; - lit.value = flattenString([a,b]); - return lit; - })(pos0, result0[0], result0[1]); + } + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, a, b) { + + if(b.length===0) { + return ("@"+a.join('')).toLowerCase(); + } else { + return ("@"+a.join('')+"-"+b[0][1].join('')).toLowerCase(); } - if (result0 === null) { - pos = pos0; + })(pos0, result0[1], result0[2]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[128] LANGTAG"); + } + return result0; + } + + function parse_INTEGER() { + var result0, result1; + var pos0; + + reportFailures++; + pos0 = pos; + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result1 !== null) { + result0 = []; + while (result1 !== null) { + result0.push(result1); + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); } } } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[131] DOUBLE"); + } else { + result0 = null; + } + if (result0 !== null) { + result0 = (function(offset, d) { + var lit = {}; + lit.token = "literal"; + lit.lang = null; + lit.type = "http://www.w3.org/2001/XMLSchema#integer"; + lit.value = flattenString(d); + return lit; + })(pos0, result0); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[129] INTEGER"); + } + return result0; + } + + function parse_DECIMAL() { + var result0, result1, result2, result3; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result1 !== null) { + result0 = []; + while (result1 !== null) { + result0.push(result1); + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } } - return result0; + } else { + result0 = null; } - - function parse_INTEGER_POSITIVE() { - var result0, result1; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 43) { - result0 = "+"; + if (result0 !== null) { + if (input.charCodeAt(pos) === 46) { + result1 = "."; pos++; } else { - result0 = null; + result1 = null; if (reportFailures === 0) { - matchFailed("\"+\""); + matchFailed("\".\""); } } - if (result0 !== null) { - result1 = parse_INTEGER(); - if (result1 !== null) { - result0 = [result0, result1]; + if (result1 !== null) { + result2 = []; + if (/^[0-9]/.test(input.charAt(pos))) { + result3 = input.charAt(pos); + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + while (result3 !== null) { + result2.push(result3); + if (/^[0-9]/.test(input.charAt(pos))) { + result3 = input.charAt(pos); + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + if (result2 !== null) { + result0 = [result0, result1, result2]; } else { result0 = null; pos = pos1; @@ -23763,37 +22852,63 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, d) { d.value = "+"+d.value; return d; })(pos0, result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[132] INTEGER_POSITIVE"); - } - return result0; + } else { + result0 = null; + pos = pos1; } - - function parse_DECIMAL_POSITIVE() { - var result0, result1; - var pos0, pos1; - - reportFailures++; + if (result0 !== null) { + result0 = (function(offset, a, b, c) { + + var lit = {}; + lit.token = "literal"; + lit.lang = null; + lit.type = "http://www.w3.org/2001/XMLSchema#decimal"; + lit.value = flattenString([a,b,c]); + return lit; + })(pos0, result0[0], result0[1], result0[2]); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { pos0 = pos; pos1 = pos; - if (input.charCodeAt(pos) === 43) { - result0 = "+"; + if (input.charCodeAt(pos) === 46) { + result0 = "."; pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("\"+\""); + matchFailed("\".\""); + } + } + if (result0 !== null) { + if (/^[0-9]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result2 !== null) { + result1 = []; + while (result2 !== null) { + result1.push(result2); + if (/^[0-9]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result1 = null; } - } - if (result0 !== null) { - result1 = parse_DECIMAL(); if (result1 !== null) { result0 = [result0, result1]; } else { @@ -23805,38 +22920,100 @@ pos = pos1; } if (result0 !== null) { - result0 = (function(offset, d) { d.value = "+"+d.value; return d })(pos0, result0[1]); + result0 = (function(offset, a, b) { + var lit = {}; + lit.token = "literal"; + lit.lang = null; + lit.type = "http://www.w3.org/2001/XMLSchema#decimal"; + lit.value = flattenString([a,b]); + return lit; + })(pos0, result0[0], result0[1]); } if (result0 === null) { pos = pos0; } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[133] DECIMAL_POSITIVE"); + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[130] DECIMAL"); + } + return result0; + } + + function parse_DOUBLE() { + var result0, result1, result2, result3; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); } - return result0; } - - function parse_DOUBLE_POSITIVE() { - var result0, result1; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 43) { - result0 = "+"; + if (result1 !== null) { + result0 = []; + while (result1 !== null) { + result0.push(result1); + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result0 = null; + } + if (result0 !== null) { + if (input.charCodeAt(pos) === 46) { + result1 = "."; pos++; } else { - result0 = null; + result1 = null; if (reportFailures === 0) { - matchFailed("\"+\""); + matchFailed("\".\""); } } - if (result0 !== null) { - result1 = parse_DOUBLE(); - if (result1 !== null) { - result0 = [result0, result1]; + if (result1 !== null) { + result2 = []; + if (/^[0-9]/.test(input.charAt(pos))) { + result3 = input.charAt(pos); + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + while (result3 !== null) { + result2.push(result3); + if (/^[0-9]/.test(input.charAt(pos))) { + result3 = input.charAt(pos); + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + if (result2 !== null) { + result3 = parse_EXPONENT(); + if (result3 !== null) { + result0 = [result0, result1, result2, result3]; + } else { + result0 = null; + pos = pos1; + } } else { result0 = null; pos = pos1; @@ -23845,39 +23022,70 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, d) { d.value = "+"+d.value; return d })(pos0, result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[134] DOUBLE_POSITIVE"); - } - return result0; + } else { + result0 = null; + pos = pos1; } - - function parse_INTEGER_NEGATIVE() { - var result0, result1; - var pos0, pos1; - - reportFailures++; + if (result0 !== null) { + result0 = (function(offset, a, b, c, e) { + var lit = {}; + lit.token = "literal"; + lit.lang = null; + lit.type = "http://www.w3.org/2001/XMLSchema#double"; + lit.value = flattenString([a,b,c,e]); + return lit; + })(pos0, result0[0], result0[1], result0[2], result0[3]); + } + if (result0 === null) { + pos = pos0; + } + if (result0 === null) { pos0 = pos; pos1 = pos; - if (input.charCodeAt(pos) === 45) { - result0 = "-"; + if (input.charCodeAt(pos) === 46) { + result0 = "."; pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("\"-\""); + matchFailed("\".\""); } } if (result0 !== null) { - result1 = parse_INTEGER(); + if (/^[0-9]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + if (result2 !== null) { + result1 = []; + while (result2 !== null) { + result1.push(result2); + if (/^[0-9]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result1 = null; + } if (result1 !== null) { - result0 = [result0, result1]; + result2 = parse_EXPONENT(); + if (result2 !== null) { + result0 = [result0, result1, result2]; + } else { + result0 = null; + pos = pos1; + } } else { result0 = null; pos = pos1; @@ -23887,160 +23095,383 @@ pos = pos1; } if (result0 !== null) { - result0 = (function(offset, d) { d.value = "-"+d.value; return d; })(pos0, result0[1]); + result0 = (function(offset, a, b, c) { + var lit = {}; + lit.token = "literal"; + lit.lang = null; + lit.type = "http://www.w3.org/2001/XMLSchema#double"; + lit.value = flattenString([a,b,c]); + return lit; + })(pos0, result0[0], result0[1], result0[2]); } if (result0 === null) { pos = pos0; } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[135] INTEGER_NEGATIVE"); - } - return result0; - } - - function parse_DECIMAL_NEGATIVE() { - var result0, result1; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 45) { - result0 = "-"; - pos++; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"-\""); + if (result0 === null) { + pos0 = pos; + pos1 = pos; + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } } - } - if (result0 !== null) { - result1 = parse_DECIMAL(); if (result1 !== null) { - result0 = [result0, result1]; + result0 = []; + while (result1 !== null) { + result0.push(result1); + if (/^[0-9]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); + pos++; + } else { + result1 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } + } + } else { + result0 = null; + } + if (result0 !== null) { + result1 = parse_EXPONENT(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } } else { result0 = null; pos = pos1; } + if (result0 !== null) { + result0 = (function(offset, a, b) { + var lit = {}; + lit.token = "literal"; + lit.lang = null; + lit.type = "http://www.w3.org/2001/XMLSchema#double"; + lit.value = flattenString([a,b]); + return lit; + })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + } + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[131] DOUBLE"); + } + return result0; + } + + function parse_INTEGER_POSITIVE() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 43) { + result0 = "+"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"+\""); + } + } + if (result0 !== null) { + result1 = parse_INTEGER(); + if (result1 !== null) { + result0 = [result0, result1]; } else { result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, d) { d.value = "-"+d.value; return d; })(pos0, result0[1]); + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, d) { d.value = "+"+d.value; return d; })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[132] INTEGER_POSITIVE"); + } + return result0; + } + + function parse_DECIMAL_POSITIVE() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 43) { + result0 = "+"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"+\""); } - if (result0 === null) { - pos = pos0; + } + if (result0 !== null) { + result1 = parse_DECIMAL(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[136] DECIMAL_NEGATIVE"); + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, d) { d.value = "+"+d.value; return d })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[133] DECIMAL_POSITIVE"); + } + return result0; + } + + function parse_DOUBLE_POSITIVE() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 43) { + result0 = "+"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"+\""); } - return result0; } - - function parse_DOUBLE_NEGATIVE() { - var result0, result1; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 45) { - result0 = "-"; - pos++; + if (result0 !== null) { + result1 = parse_DOUBLE(); + if (result1 !== null) { + result0 = [result0, result1]; } else { result0 = null; - if (reportFailures === 0) { - matchFailed("\"-\""); - } + pos = pos1; } - if (result0 !== null) { - result1 = parse_DOUBLE(); - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, d) { d.value = "+"+d.value; return d })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[134] DOUBLE_POSITIVE"); + } + return result0; + } + + function parse_INTEGER_NEGATIVE() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 45) { + result0 = "-"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"-\""); + } + } + if (result0 !== null) { + result1 = parse_INTEGER(); + if (result1 !== null) { + result0 = [result0, result1]; } else { result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, d) { d.value = "-"+d.value; return d; })(pos0, result0[1]); + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, d) { d.value = "-"+d.value; return d; })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[135] INTEGER_NEGATIVE"); + } + return result0; + } + + function parse_DECIMAL_NEGATIVE() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 45) { + result0 = "-"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"-\""); } - if (result0 === null) { - pos = pos0; + } + if (result0 !== null) { + result1 = parse_DECIMAL(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; + } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, d) { d.value = "-"+d.value; return d; })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[136] DECIMAL_NEGATIVE"); + } + return result0; + } + + function parse_DOUBLE_NEGATIVE() { + var result0, result1; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 45) { + result0 = "-"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"-\""); + } + } + if (result0 !== null) { + result1 = parse_DOUBLE(); + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos1; } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[137] DOUBLE_NEGATIVE"); + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, d) { d.value = "-"+d.value; return d; })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[137] DOUBLE_NEGATIVE"); + } + return result0; + } + + function parse_EXPONENT() { + var result0, result1, result2, result3; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (/^[eE]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[eE]"); } - return result0; } - - function parse_EXPONENT() { - var result0, result1, result2, result3; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (/^[eE]/.test(input.charAt(pos))) { - result0 = input.charAt(pos); + if (result0 !== null) { + if (/^[+\-]/.test(input.charAt(pos))) { + result1 = input.charAt(pos); pos++; } else { - result0 = null; + result1 = null; if (reportFailures === 0) { - matchFailed("[eE]"); + matchFailed("[+\\-]"); } } - if (result0 !== null) { - if (/^[+\-]/.test(input.charAt(pos))) { - result1 = input.charAt(pos); + result1 = result1 !== null ? result1 : ""; + if (result1 !== null) { + if (/^[0-9]/.test(input.charAt(pos))) { + result3 = input.charAt(pos); pos++; } else { - result1 = null; + result3 = null; if (reportFailures === 0) { - matchFailed("[+\\-]"); + matchFailed("[0-9]"); } } - result1 = result1 !== null ? result1 : ""; - if (result1 !== null) { - if (/^[0-9]/.test(input.charAt(pos))) { - result3 = input.charAt(pos); - pos++; - } else { - result3 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } - } - if (result3 !== null) { - result2 = []; - while (result3 !== null) { - result2.push(result3); - if (/^[0-9]/.test(input.charAt(pos))) { - result3 = input.charAt(pos); - pos++; - } else { - result3 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } + if (result3 !== null) { + result2 = []; + while (result3 !== null) { + result2.push(result3); + if (/^[0-9]/.test(input.charAt(pos))) { + result3 = input.charAt(pos); + pos++; + } else { + result3 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); } } - } else { - result2 = null; - } - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos1; } + } else { + result2 = null; + } + if (result2 !== null) { + result0 = [result0, result1, result2]; } else { result0 = null; pos = pos1; @@ -24049,37 +23480,55 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, a, b, c) { return flattenString([a,b,c]) })(pos0, result0[0], result0[1], result0[2]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[138] EXPONENT"); + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, a, b, c) { return flattenString([a,b,c]) })(pos0, result0[0], result0[1], result0[2]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[138] EXPONENT"); + } + return result0; + } + + function parse_STRING_LITERAL1() { + var result0, result1, result2; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 39) { + result0 = "'"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"'\""); } - return result0; } - - function parse_STRING_LITERAL1() { - var result0, result1, result2; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 39) { - result0 = "'"; + if (result0 !== null) { + result1 = []; + if (/^[^'\\\n\r]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); pos++; } else { - result0 = null; + result2 = null; if (reportFailures === 0) { - matchFailed("\"'\""); + matchFailed("[^'\\\\\\n\\r]"); } } - if (result0 !== null) { - result1 = []; + if (result2 === null) { + result2 = parse_ECHAR(); + } + while (result2 !== null) { + result1.push(result2); if (/^[^'\\\n\r]/.test(input.charAt(pos))) { result2 = input.charAt(pos); pos++; @@ -24092,37 +23541,19 @@ if (result2 === null) { result2 = parse_ECHAR(); } - while (result2 !== null) { - result1.push(result2); - if (/^[^'\\\n\r]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[^'\\\\\\n\\r]"); - } - } - if (result2 === null) { - result2 = parse_ECHAR(); + } + if (result1 !== null) { + if (input.charCodeAt(pos) === 39) { + result2 = "'"; + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"'\""); } } - if (result1 !== null) { - if (input.charCodeAt(pos) === 39) { - result2 = "'"; - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("\"'\""); - } - } - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos1; - } + if (result2 !== null) { + result0 = [result0, result1, result2]; } else { result0 = null; pos = pos1; @@ -24131,37 +23562,55 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, content) { return flattenString(content) })(pos0, result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[139] STRING_LITERAL1"); + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, content) { return flattenString(content) })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[139] STRING_LITERAL1"); + } + return result0; + } + + function parse_STRING_LITERAL2() { + var result0, result1, result2; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 34) { + result0 = "\""; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\\"\""); } - return result0; } - - function parse_STRING_LITERAL2() { - var result0, result1, result2; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 34) { - result0 = "\""; + if (result0 !== null) { + result1 = []; + if (/^[^"\\\n\r]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); pos++; } else { - result0 = null; + result2 = null; if (reportFailures === 0) { - matchFailed("\"\\\"\""); + matchFailed("[^\"\\\\\\n\\r]"); } } - if (result0 !== null) { - result1 = []; + if (result2 === null) { + result2 = parse_ECHAR(); + } + while (result2 !== null) { + result1.push(result2); if (/^[^"\\\n\r]/.test(input.charAt(pos))) { result2 = input.charAt(pos); pos++; @@ -24174,119 +23623,19 @@ if (result2 === null) { result2 = parse_ECHAR(); } - while (result2 !== null) { - result1.push(result2); - if (/^[^"\\\n\r]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[^\"\\\\\\n\\r]"); - } - } - if (result2 === null) { - result2 = parse_ECHAR(); - } - } - if (result1 !== null) { - if (input.charCodeAt(pos) === 34) { - result2 = "\""; - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("\"\\\"\""); - } - } - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - } else { - result0 = null; - pos = pos1; - } - if (result0 !== null) { - result0 = (function(offset, content) { return flattenString(content) })(pos0, result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[140] STRING_LITERAL2"); - } - return result0; - } - - function parse_STRING_LITERAL_LONG1() { - var result0, result1, result2; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.substr(pos, 3) === "'''") { - result0 = "'''"; - pos += 3; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"'''\""); - } } - if (result0 !== null) { - result1 = []; - if (/^[^'\\]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); + if (result1 !== null) { + if (input.charCodeAt(pos) === 34) { + result2 = "\""; pos++; } else { result2 = null; if (reportFailures === 0) { - matchFailed("[^'\\\\]"); - } - } - if (result2 === null) { - result2 = parse_ECHAR(); - } - while (result2 !== null) { - result1.push(result2); - if (/^[^'\\]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[^'\\\\]"); - } - } - if (result2 === null) { - result2 = parse_ECHAR(); + matchFailed("\"\\\"\""); } } - if (result1 !== null) { - if (input.substr(pos, 3) === "'''") { - result2 = "'''"; - pos += 3; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("\"'''\""); - } - } - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos1; - } + if (result2 !== null) { + result0 = [result0, result1, result2]; } else { result0 = null; pos = pos1; @@ -24295,80 +23644,80 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, content) { return flattenString(content) })(pos0, result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[141] STRING_LITERAL_LONG1"); + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, content) { return flattenString(content) })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[140] STRING_LITERAL2"); + } + return result0; + } + + function parse_STRING_LITERAL_LONG1() { + var result0, result1, result2; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.substr(pos, 3) === "'''") { + result0 = "'''"; + pos += 3; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"'''\""); } - return result0; } - - function parse_STRING_LITERAL_LONG2() { - var result0, result1, result2; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.substr(pos, 3) === "\"\"\"") { - result0 = "\"\"\""; - pos += 3; + if (result0 !== null) { + result1 = []; + if (/^[^'\\]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); + pos++; } else { - result0 = null; + result2 = null; if (reportFailures === 0) { - matchFailed("\"\\\"\\\"\\\"\""); + matchFailed("[^'\\\\]"); } } - if (result0 !== null) { - result1 = []; - if (/^[^"\\]/.test(input.charAt(pos))) { + if (result2 === null) { + result2 = parse_ECHAR(); + } + while (result2 !== null) { + result1.push(result2); + if (/^[^'\\]/.test(input.charAt(pos))) { result2 = input.charAt(pos); pos++; } else { result2 = null; if (reportFailures === 0) { - matchFailed("[^\"\\\\]"); - } - } - if (result2 === null) { - result2 = parse_ECHAR(); - } - while (result2 !== null) { - result1.push(result2); - if (/^[^"\\]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[^\"\\\\]"); - } - } - if (result2 === null) { - result2 = parse_ECHAR(); - } - } - if (result1 !== null) { - if (input.substr(pos, 3) === "\"\"\"") { - result2 = "\"\"\""; - pos += 3; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("\"\\\"\\\"\\\"\""); - } - } - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos1; + matchFailed("[^'\\\\]"); } + } + if (result2 === null) { + result2 = parse_ECHAR(); + } + } + if (result1 !== null) { + if (input.substr(pos, 3) === "'''") { + result2 = "'''"; + pos += 3; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"'''\""); + } + } + if (result2 !== null) { + result0 = [result0, result1, result2]; } else { result0 = null; pos = pos1; @@ -24377,100 +23726,182 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, content) { return flattenString(content) })(pos0, result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[142] STRING_LITERAL_LONG2"); + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, content) { return flattenString(content) })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[141] STRING_LITERAL_LONG1"); + } + return result0; + } + + function parse_STRING_LITERAL_LONG2() { + var result0, result1, result2; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.substr(pos, 3) === "\"\"\"") { + result0 = "\"\"\""; + pos += 3; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\\"\\\"\\\"\""); } - return result0; } - - function parse_ECHAR() { - var result0, result1; - var pos0; - - reportFailures++; - pos0 = pos; - if (input.charCodeAt(pos) === 92) { - result0 = "\\"; + if (result0 !== null) { + result1 = []; + if (/^[^"\\]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); pos++; } else { - result0 = null; + result2 = null; if (reportFailures === 0) { - matchFailed("\"\\\\\""); + matchFailed("[^\"\\\\]"); } } - if (result0 !== null) { - if (/^[tbnrf"']/.test(input.charAt(pos))) { - result1 = input.charAt(pos); + if (result2 === null) { + result2 = parse_ECHAR(); + } + while (result2 !== null) { + result1.push(result2); + if (/^[^"\\]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); pos++; } else { - result1 = null; + result2 = null; + if (reportFailures === 0) { + matchFailed("[^\"\\\\]"); + } + } + if (result2 === null) { + result2 = parse_ECHAR(); + } + } + if (result1 !== null) { + if (input.substr(pos, 3) === "\"\"\"") { + result2 = "\"\"\""; + pos += 3; + } else { + result2 = null; if (reportFailures === 0) { - matchFailed("[tbnrf\"']"); + matchFailed("\"\\\"\\\"\\\"\""); } } - if (result1 !== null) { - result0 = [result0, result1]; + if (result2 !== null) { + result0 = [result0, result1, result2]; } else { result0 = null; - pos = pos0; + pos = pos1; } } else { result0 = null; - pos = pos0; + pos = pos1; } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[143] ECHAR"); + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, content) { return flattenString(content) })(pos0, result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[142] STRING_LITERAL_LONG2"); + } + return result0; + } + + function parse_ECHAR() { + var result0, result1; + var pos0; + + reportFailures++; + pos0 = pos; + if (input.charCodeAt(pos) === 92) { + result0 = "\\"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"\\\\\""); } - return result0; } - - function parse_NIL() { - var result0, result1, result2; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - if (input.charCodeAt(pos) === 40) { - result0 = "("; + if (result0 !== null) { + if (/^[tbnrf"']/.test(input.charAt(pos))) { + result1 = input.charAt(pos); pos++; } else { - result0 = null; + result1 = null; if (reportFailures === 0) { - matchFailed("\"(\""); + matchFailed("[tbnrf\"']"); } } - if (result0 !== null) { - result1 = []; + if (result1 !== null) { + result0 = [result0, result1]; + } else { + result0 = null; + pos = pos0; + } + } else { + result0 = null; + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[143] ECHAR"); + } + return result0; + } + + function parse_NIL() { + var result0, result1, result2; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + if (input.charCodeAt(pos) === 40) { + result0 = "("; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"(\""); + } + } + if (result0 !== null) { + result1 = []; + result2 = parse_WS(); + while (result2 !== null) { + result1.push(result2); result2 = parse_WS(); - while (result2 !== null) { - result1.push(result2); - result2 = parse_WS(); - } - if (result1 !== null) { - if (input.charCodeAt(pos) === 41) { - result2 = ")"; - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("\")\""); - } - } - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos1; + } + if (result1 !== null) { + if (input.charCodeAt(pos) === 41) { + result2 = ")"; + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\")\""); } + } + if (result2 !== null) { + result0 = [result0, result1, result2]; } else { result0 = null; pos = pos1; @@ -24479,97 +23910,112 @@ result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset) { - - return {token: "triplesnodecollection", - triplesContext:[], - chainSubject:[{token:'uri', value:"http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"}]}; - })(pos0); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[144] NIL"); + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset) { + + return {token: "triplesnodecollection", + triplesContext:[], + chainSubject:[{token:'uri', value:"http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"}]}; + })(pos0); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[144] NIL"); + } + return result0; + } + + function parse_WS() { + var result0; + + reportFailures++; + if (/^[ ]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[ ]"); } - return result0; } - - function parse_WS() { - var result0; - - reportFailures++; - if (/^[ ]/.test(input.charAt(pos))) { + if (result0 === null) { + if (/^[\t]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[ ]"); + matchFailed("[\\t]"); } } if (result0 === null) { - if (/^[\t]/.test(input.charAt(pos))) { + if (/^[\r]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\t]"); + matchFailed("[\\r]"); } } if (result0 === null) { - if (/^[\r]/.test(input.charAt(pos))) { + if (/^[\n]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\r]"); + matchFailed("[\\n]"); } } if (result0 === null) { - if (/^[\n]/.test(input.charAt(pos))) { - result0 = input.charAt(pos); - pos++; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("[\\n]"); - } - } - if (result0 === null) { - result0 = parse_COMMENT(); - } + result0 = parse_COMMENT(); } } } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[145] WS"); + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[145] WS"); + } + return result0; + } + + function parse_COMMENT() { + var result0, result1, result2; + var pos0; + + reportFailures++; + pos0 = pos; + if (input.charCodeAt(pos) === 35) { + result0 = "#"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"#\""); } - return result0; } - - function parse_COMMENT() { - var result0, result1, result2; - var pos0; - - reportFailures++; - pos0 = pos; - if (input.charCodeAt(pos) === 35) { - result0 = "#"; + if (result0 !== null) { + result1 = []; + if (/^[^\n\r]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); pos++; } else { - result0 = null; + result2 = null; if (reportFailures === 0) { - matchFailed("\"#\""); + matchFailed("[^\\n\\r]"); } } - if (result0 !== null) { - result1 = []; + while (result2 !== null) { + result1.push(result2); if (/^[^\n\r]/.test(input.charAt(pos))) { result2 = input.charAt(pos); pos++; @@ -24579,73 +24025,58 @@ matchFailed("[^\\n\\r]"); } } - while (result2 !== null) { - result1.push(result2); - if (/^[^\n\r]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[^\\n\\r]"); - } - } - } - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos0; - } + } + if (result1 !== null) { + result0 = [result0, result1]; } else { result0 = null; pos = pos0; } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed(" COMMENT"); + } else { + result0 = null; + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed(" COMMENT"); + } + return result0; + } + + function parse_ANON() { + var result0, result1, result2; + var pos0; + + reportFailures++; + pos0 = pos; + if (input.charCodeAt(pos) === 91) { + result0 = "["; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"[\""); } - return result0; } - - function parse_ANON() { - var result0, result1, result2; - var pos0; - - reportFailures++; - pos0 = pos; - if (input.charCodeAt(pos) === 91) { - result0 = "["; - pos++; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"[\""); - } - } - if (result0 !== null) { - result1 = []; + if (result0 !== null) { + result1 = []; + result2 = parse_WS(); + while (result2 !== null) { + result1.push(result2); result2 = parse_WS(); - while (result2 !== null) { - result1.push(result2); - result2 = parse_WS(); - } - if (result1 !== null) { - if (input.charCodeAt(pos) === 93) { - result2 = "]"; - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("\"]\""); - } - } - if (result2 !== null) { - result0 = [result0, result1, result2]; - } else { - result0 = null; - pos = pos0; + } + if (result1 !== null) { + if (input.charCodeAt(pos) === 93) { + result2 = "]"; + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\"]\""); } + } + if (result2 !== null) { + result0 = [result0, result1, result2]; } else { result0 = null; pos = pos0; @@ -24654,155 +24085,158 @@ result0 = null; pos = pos0; } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[146] ANON"); + } else { + result0 = null; + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[146] ANON"); + } + return result0; + } + + function parse_PN_CHARS_BASE() { + var result0; + + reportFailures++; + if (/^[A-Z]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[A-Z]"); } - return result0; } - - function parse_PN_CHARS_BASE() { - var result0; - - reportFailures++; - if (/^[A-Z]/.test(input.charAt(pos))) { + if (result0 === null) { + if (/^[a-z]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[A-Z]"); + matchFailed("[a-z]"); } } if (result0 === null) { - if (/^[a-z]/.test(input.charAt(pos))) { + if (/^[\xC0-\xD6]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[a-z]"); + matchFailed("[\\xC0-\\xD6]"); } } if (result0 === null) { - if (/^[\xC0-\xD6]/.test(input.charAt(pos))) { + if (/^[\xD8-\xF6]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\xC0-\\xD6]"); + matchFailed("[\\xD8-\\xF6]"); } } if (result0 === null) { - if (/^[\xD8-\xF6]/.test(input.charAt(pos))) { + if (/^[\xF8-\u02FF]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\xD8-\\xF6]"); + matchFailed("[\\xF8-\\u02FF]"); } } if (result0 === null) { - if (/^[\xF8-\u02FF]/.test(input.charAt(pos))) { + if (/^[\u0370-\u037D]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\xF8-\\u02FF]"); + matchFailed("[\\u0370-\\u037D]"); } } if (result0 === null) { - if (/^[\u0370-\u037D]/.test(input.charAt(pos))) { + if (/^[\u037F-\u1FFF]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\u0370-\\u037D]"); + matchFailed("[\\u037F-\\u1FFF]"); } } if (result0 === null) { - if (/^[\u037F-\u1FFF]/.test(input.charAt(pos))) { + if (/^[\u200C-\u200D]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\u037F-\\u1FFF]"); + matchFailed("[\\u200C-\\u200D]"); } } if (result0 === null) { - if (/^[\u200C-\u200D]/.test(input.charAt(pos))) { + if (/^[\u2070-\u218F]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\u200C-\\u200D]"); + matchFailed("[\\u2070-\\u218F]"); } } if (result0 === null) { - if (/^[\u2070-\u218F]/.test(input.charAt(pos))) { + if (/^[\u2C00-\u2FEF]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\u2070-\\u218F]"); + matchFailed("[\\u2C00-\\u2FEF]"); } } if (result0 === null) { - if (/^[\u2C00-\u2FEF]/.test(input.charAt(pos))) { + if (/^[\u3001-\uD7FF]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\u2C00-\\u2FEF]"); + matchFailed("[\\u3001-\\uD7FF]"); } } if (result0 === null) { - if (/^[\u3001-\uD7FF]/.test(input.charAt(pos))) { + if (/^[\uF900-\uFDCF]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\u3001-\\uD7FF]"); + matchFailed("[\\uF900-\\uFDCF]"); } } if (result0 === null) { - if (/^[\uF900-\uFDCF]/.test(input.charAt(pos))) { + if (/^[\uFDF0-\uFFFD]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\uF900-\\uFDCF]"); + matchFailed("[\\uFDF0-\\uFFFD]"); } } if (result0 === null) { - if (/^[\uFDF0-\uFFFD]/.test(input.charAt(pos))) { + if (/^[\u1000-\uEFFF]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\uFDF0-\\uFFFD]"); - } - } - if (result0 === null) { - if (/^[\u1000-\uEFFF]/.test(input.charAt(pos))) { - result0 = input.charAt(pos); - pos++; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("[\\u1000-\\uEFFF]"); - } + matchFailed("[\\u1000-\\uEFFF]"); } } } @@ -24817,250 +24251,265 @@ } } } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[147] PN_CHARS_BASE"); - } - return result0; } - - function parse_PN_CHARS_U() { - var result0; - - reportFailures++; - result0 = parse_PN_CHARS_BASE(); - if (result0 === null) { - if (input.charCodeAt(pos) === 95) { - result0 = "_"; - pos++; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("\"_\""); - } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[147] PN_CHARS_BASE"); + } + return result0; + } + + function parse_PN_CHARS_U() { + var result0; + + reportFailures++; + result0 = parse_PN_CHARS_BASE(); + if (result0 === null) { + if (input.charCodeAt(pos) === 95) { + result0 = "_"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"_\""); } } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[148] PN_CHARS_U"); + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[148] PN_CHARS_U"); + } + return result0; + } + + function parse_VARNAME() { + var result0, result1, result2; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = parse_PN_CHARS_U(); + if (result0 === null) { + if (/^[0-9]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } } - return result0; } - - function parse_VARNAME() { - var result0, result1, result2; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = parse_PN_CHARS_U(); - if (result0 === null) { + if (result0 !== null) { + result1 = []; + result2 = parse_PN_CHARS_U(); + if (result2 === null) { if (/^[0-9]/.test(input.charAt(pos))) { - result0 = input.charAt(pos); + result2 = input.charAt(pos); pos++; } else { - result0 = null; + result2 = null; if (reportFailures === 0) { matchFailed("[0-9]"); } } - } - if (result0 !== null) { - result1 = []; - result2 = parse_PN_CHARS_U(); if (result2 === null) { - if (/^[0-9]/.test(input.charAt(pos))) { + if (/^[\xB7]/.test(input.charAt(pos))) { result2 = input.charAt(pos); pos++; } else { result2 = null; if (reportFailures === 0) { - matchFailed("[0-9]"); + matchFailed("[\\xB7]"); } } if (result2 === null) { - if (/^[\xB7]/.test(input.charAt(pos))) { + if (/^[\u0300-\u036F]/.test(input.charAt(pos))) { result2 = input.charAt(pos); pos++; } else { result2 = null; if (reportFailures === 0) { - matchFailed("[\\xB7]"); + matchFailed("[\\u0300-\\u036F]"); } } if (result2 === null) { - if (/^[\u0300-\u036F]/.test(input.charAt(pos))) { + if (/^[\u203F-\u2040]/.test(input.charAt(pos))) { result2 = input.charAt(pos); pos++; } else { result2 = null; if (reportFailures === 0) { - matchFailed("[\\u0300-\\u036F]"); - } - } - if (result2 === null) { - if (/^[\u203F-\u2040]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[\\u203F-\\u2040]"); - } + matchFailed("[\\u203F-\\u2040]"); } } } } } - while (result2 !== null) { - result1.push(result2); - result2 = parse_PN_CHARS_U(); + } + while (result2 !== null) { + result1.push(result2); + result2 = parse_PN_CHARS_U(); + if (result2 === null) { + if (/^[0-9]/.test(input.charAt(pos))) { + result2 = input.charAt(pos); + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); + } + } if (result2 === null) { - if (/^[0-9]/.test(input.charAt(pos))) { + if (/^[\xB7]/.test(input.charAt(pos))) { result2 = input.charAt(pos); pos++; } else { result2 = null; if (reportFailures === 0) { - matchFailed("[0-9]"); + matchFailed("[\\xB7]"); } } if (result2 === null) { - if (/^[\xB7]/.test(input.charAt(pos))) { + if (/^[\u0300-\u036F]/.test(input.charAt(pos))) { result2 = input.charAt(pos); pos++; } else { result2 = null; if (reportFailures === 0) { - matchFailed("[\\xB7]"); + matchFailed("[\\u0300-\\u036F]"); } } if (result2 === null) { - if (/^[\u0300-\u036F]/.test(input.charAt(pos))) { + if (/^[\u203F-\u2040]/.test(input.charAt(pos))) { result2 = input.charAt(pos); pos++; } else { result2 = null; if (reportFailures === 0) { - matchFailed("[\\u0300-\\u036F]"); - } - } - if (result2 === null) { - if (/^[\u203F-\u2040]/.test(input.charAt(pos))) { - result2 = input.charAt(pos); - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("[\\u203F-\\u2040]"); - } + matchFailed("[\\u203F-\\u2040]"); } } } } } } - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } + } + if (result1 !== null) { + result0 = [result0, result1]; } else { result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, init, rpart) { return init+rpart.join('') })(pos0, result0[0], result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[149] VARNAME"); - } - return result0; + } else { + result0 = null; + pos = pos1; } - - function parse_PN_CHARS() { - var result0; - - reportFailures++; - result0 = parse_PN_CHARS_U(); + if (result0 !== null) { + result0 = (function(offset, init, rpart) { return init+rpart.join('') })(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[149] VARNAME"); + } + return result0; + } + + function parse_PN_CHARS() { + var result0; + + reportFailures++; + result0 = parse_PN_CHARS_U(); + if (result0 === null) { + if (input.charCodeAt(pos) === 45) { + result0 = "-"; + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("\"-\""); + } + } if (result0 === null) { - if (input.charCodeAt(pos) === 45) { - result0 = "-"; + if (/^[0-9]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("\"-\""); + matchFailed("[0-9]"); } } if (result0 === null) { - if (/^[0-9]/.test(input.charAt(pos))) { + if (/^[\xB7]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[0-9]"); + matchFailed("[\\xB7]"); } } if (result0 === null) { - if (/^[\xB7]/.test(input.charAt(pos))) { + if (/^[\u0300-\u036F]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\xB7]"); + matchFailed("[\\u0300-\\u036F]"); } } if (result0 === null) { - if (/^[\u0300-\u036F]/.test(input.charAt(pos))) { + if (/^[\u203F-\u2040]/.test(input.charAt(pos))) { result0 = input.charAt(pos); pos++; } else { result0 = null; if (reportFailures === 0) { - matchFailed("[\\u0300-\\u036F]"); - } - } - if (result0 === null) { - if (/^[\u203F-\u2040]/.test(input.charAt(pos))) { - result0 = input.charAt(pos); - pos++; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("[\\u203F-\\u2040]"); - } + matchFailed("[\\u203F-\\u2040]"); } } } } } } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[150] PN_CHARS"); - } - return result0; } - - function parse_PN_PREFIX() { - var result0, result1, result2; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = parse_PN_CHARS_BASE(); - if (result0 !== null) { - result1 = []; + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[150] PN_CHARS"); + } + return result0; + } + + function parse_PN_PREFIX() { + var result0, result1, result2; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = parse_PN_CHARS_BASE(); + if (result0 !== null) { + result1 = []; + result2 = parse_PN_CHARS(); + if (result2 === null) { + if (input.charCodeAt(pos) === 46) { + result2 = "."; + pos++; + } else { + result2 = null; + if (reportFailures === 0) { + matchFailed("\".\""); + } + } + } + while (result2 !== null) { + result1.push(result2); result2 = parse_PN_CHARS(); if (result2 === null) { if (input.charCodeAt(pos) === 46) { @@ -25073,1305 +24522,1291 @@ } } } - while (result2 !== null) { - result1.push(result2); - result2 = parse_PN_CHARS(); - if (result2 === null) { - if (input.charCodeAt(pos) === 46) { - result2 = "."; - pos++; - } else { - result2 = null; - if (reportFailures === 0) { - matchFailed("\".\""); - } - } - } - } - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } + } + if (result1 !== null) { + result0 = [result0, result1]; } else { result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, base, rest) { if(rest[rest.length-1] == '.'){ - throw new Error("Wrong PN_PREFIX, cannot finish with '.'") - } else { - return base + rest.join(''); - }})(pos0, result0[0], result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[151] PN_PREFIX"); - } - return result0; - } - - function parse_PN_LOCAL() { - var result0, result1, result2; - var pos0, pos1; - - reportFailures++; - pos0 = pos; - pos1 = pos; - result0 = parse_PN_CHARS_U(); - if (result0 === null) { - if (/^[0-9]/.test(input.charAt(pos))) { - result0 = input.charAt(pos); - pos++; - } else { - result0 = null; - if (reportFailures === 0) { - matchFailed("[0-9]"); - } + } else { + result0 = null; + pos = pos1; + } + if (result0 !== null) { + result0 = (function(offset, base, rest) { if(rest[rest.length-1] == '.'){ + throw new Error("Wrong PN_PREFIX, cannot finish with '.'") + } else { + return base + rest.join(''); + }})(pos0, result0[0], result0[1]); + } + if (result0 === null) { + pos = pos0; + } + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[151] PN_PREFIX"); + } + return result0; + } + + function parse_PN_LOCAL() { + var result0, result1, result2; + var pos0, pos1; + + reportFailures++; + pos0 = pos; + pos1 = pos; + result0 = parse_PN_CHARS_U(); + if (result0 === null) { + if (/^[0-9]/.test(input.charAt(pos))) { + result0 = input.charAt(pos); + pos++; + } else { + result0 = null; + if (reportFailures === 0) { + matchFailed("[0-9]"); } } - if (result0 !== null) { - result1 = []; + } + if (result0 !== null) { + result1 = []; + result2 = parse_PN_CHARS(); + while (result2 !== null) { + result1.push(result2); result2 = parse_PN_CHARS(); - while (result2 !== null) { - result1.push(result2); - result2 = parse_PN_CHARS(); - } - if (result1 !== null) { - result0 = [result0, result1]; - } else { - result0 = null; - pos = pos1; - } + } + if (result1 !== null) { + result0 = [result0, result1]; } else { result0 = null; pos = pos1; } - if (result0 !== null) { - result0 = (function(offset, base, rest) { - return base + rest.join(''); - })(pos0, result0[0], result0[1]); - } - if (result0 === null) { - pos = pos0; - } - reportFailures--; - if (reportFailures === 0 && result0 === null) { - matchFailed("[152] PN_LOCAL"); - } - return result0; - } - - - function cleanupExpected(expected) { - expected.sort(); - - var lastExpected = null; - var cleanExpected = []; - for (var i = 0; i < expected.length; i++) { - if (expected[i] !== lastExpected) { - cleanExpected.push(expected[i]); - lastExpected = expected[i]; - } - } - return cleanExpected; - } - - function computeErrorPosition() { - /* - * The first idea was to use |String.split| to break the input up to the - * error position along newlines and derive the line and column from - * there. However IE's |split| implementation is so broken that it was - * enough to prevent it. - */ - - var line = 1; - var column = 1; - var seenCR = false; - - for (var i = 0; i < Math.max(pos, rightmostFailuresPos); i++) { - var ch = input.charAt(i); - if (ch === "\n") { - if (!seenCR) { line++; } - column = 1; - seenCR = false; - } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { - line++; - column = 1; - seenCR = true; - } else { - column++; - seenCR = false; - } - } - - return { line: line, column: column }; + } else { + result0 = null; + pos = pos1; } - - - var flattenString = function(arrs) { - var acum =""; - for(var i=0; i< arrs.length; i++) { - if(typeof(arrs[i])==='string') { - acum = acum + arrs[i]; - } else { - acum = acum + arrs[i].join(''); - } - } - - return acum; + if (result0 !== null) { + result0 = (function(offset, base, rest) { + return base + rest.join(''); + })(pos0, result0[0], result0[1]); } - - - var GlobalBlankNodeCounter = 0; - - var prefixes = {}; - - var registerPrefix = function(prefix, uri) { - prefixes[prefix] = uri; + if (result0 === null) { + pos = pos0; } - - var registerDefaultPrefix = function(uri) { - prefixes[null] = uri; + reportFailures--; + if (reportFailures === 0 && result0 === null) { + matchFailed("[152] PN_LOCAL"); } - - var arrayToString = function(array) { - var tmp = ""; - for(var i=0; i - */ +/** + * Implementation of + */ // Uris map - RDFJSInterface.defaultContext = { "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", - "rdfs": "http://www.w3.org/2000/01/rdf-schema#", - "owl": "http://www.w3.org/2002/07/owl#", - "xsd": "http://www.w3.org/2001/XMLSchema#", - "dcterms": "http://purl.org/dc/terms/", - "foaf": "http://xmlns.com/foaf/0.1/", - "cal": "http://www.w3.org/2002/12/cal/ical#", - "vcard": "http://www.w3.org/2006/vcard/ns# ", - "geo": "http://www.w3.org/2003/01/geo/wgs84_pos#", - "cc": "http://creativecommons.org/ns#", - "sioc": "http://rdfs.org/sioc/ns#", - "doap": "http://usefulinc.com/ns/doap#", - "com": "http://purl.org/commerce#", - "ps": "http://purl.org/payswarm#", - "gr": "http://purl.org/goodrelations/v1#", - "sig": "http://purl.org/signature#", - "ccard": "http://purl.org/commerce/creditcard#" - }; - - RDFJSInterface.UrisMap = function() { +RDFJSInterface.defaultContext = { "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "owl": "http://www.w3.org/2002/07/owl#", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "dcterms": "http://purl.org/dc/terms/", + "foaf": "http://xmlns.com/foaf/0.1/", + "cal": "http://www.w3.org/2002/12/cal/ical#", + "vcard": "http://www.w3.org/2006/vcard/ns# ", + "geo": "http://www.w3.org/2003/01/geo/wgs84_pos#", + "cc": "http://creativecommons.org/ns#", + "sioc": "http://rdfs.org/sioc/ns#", + "doap": "http://usefulinc.com/ns/doap#", + "com": "http://purl.org/commerce#", + "ps": "http://purl.org/payswarm#", + "gr": "http://purl.org/goodrelations/v1#", + "sig": "http://purl.org/signature#", + "ccard": "http://purl.org/commerce/creditcard#" + }; + +RDFJSInterface.UrisMap = function() { this.defaultNs = ""; this.interfaceProperties = ['get', 'remove', 'set', 'setDefault', - 'addAll', 'resolve', 'shrink']; - }; + 'addAll', 'resolve', 'shrink']; +}; - RDFJSInterface.UrisMap.prototype.values = function() { +RDFJSInterface.UrisMap.prototype.values = function() { var collected = {}; for(var p in this) { - if(!Utils.include(this.interfaceProperties,p) && - typeof(this[p])!=='function' && - p!=='defaultNs' && - p!=='interfaceProperties') { - collected[p] = this[p]; - } + if(!Utils.include(this.interfaceProperties,p) && + typeof(this[p])!=='function' && + p!=='defaultNs' && + p!=='interfaceProperties') { + collected[p] = this[p]; + } } return collected; - }; +}; - RDFJSInterface.UrisMap.prototype.get = function(prefix) { +RDFJSInterface.UrisMap.prototype.get = function(prefix) { if(prefix.indexOf(" ") != -1) { - throw "Prefix must not contain any whitespaces"; + throw "Prefix must not contain any whitespaces"; } return this[prefix]; - }; +}; - RDFJSInterface.UrisMap.prototype.remove = function(prefix) { +RDFJSInterface.UrisMap.prototype.remove = function(prefix) { if(prefix.indexOf(" ") != -1) { - throw "Prefix must not contain any whitespaces"; + throw "Prefix must not contain any whitespaces"; } delete this[prefix]; return null; - }; +}; - RDFJSInterface.UrisMap.prototype.set = function(prefix, iri) { +RDFJSInterface.UrisMap.prototype.set = function(prefix, iri) { if(prefix.indexOf(" ") != -1) { - throw "Prefix must not contain any whitespaces"; + throw "Prefix must not contain any whitespaces"; } this[prefix] = iri; - }; +}; - RDFJSInterface.UrisMap.prototype.setDefault = function(iri) { +RDFJSInterface.UrisMap.prototype.setDefault = function(iri) { this.defaultNs =iri; - }; +}; - RDFJSInterface.UrisMap.prototype.addAll = function(prefixMap, override) { +RDFJSInterface.UrisMap.prototype.addAll = function(prefixMap, override) { for(var prefix in prefixMap) { - if(!Utils.include(this.interfaceProperties, prefix)) { - if(this[prefix] != null) { - if(override === true) { - this[prefix] = prefixMap[prefix]; - } - } else { - this[prefix] = prefixMap[prefix]; + if(!Utils.include(this.interfaceProperties, prefix)) { + if(this[prefix] != null) { + if(override === true) { + this[prefix] = prefixMap[prefix]; + } + } else { + this[prefix] = prefixMap[prefix]; + } } - } } return this; - }; +}; - RDFJSInterface.UrisMap.prototype.resolve = function(curie) { +RDFJSInterface.UrisMap.prototype.resolve = function(curie) { var parts = curie.split(":"); var ns = parts[0]; var suffix = parts[1]; if(ns === '') { - if(this.defaultNs == null) { - return null; - } else { - return this.defaultNs + suffix; - } + if(this.defaultNs == null) { + return null; + } else { + return this.defaultNs + suffix; + } } else if(this.hasOwnProperty(ns)) { - return this[ns] + suffix; + return this[ns] + suffix; } else { - return null; + return null; } - }; +}; - RDFJSInterface.UrisMap.prototype.shrink = function(iri) { +RDFJSInterface.UrisMap.prototype.shrink = function(iri) { for(var ns in this) { - var prefix = this[ns]; - if(iri.indexOf(prefix) === 0) { - if(prefix !== '' && ns != 'defaultNs') { - var suffix = iri.split(prefix)[1]; - return ns + ":" + suffix; + var prefix = this[ns]; + if(iri.indexOf(prefix) === 0) { + if(prefix !== '' && ns != 'defaultNs') { + var suffix = iri.split(prefix)[1]; + return ns + ":" + suffix; + } } - } } return iri; - }; +}; // Profile - RDFJSInterface.Profile = function() { +RDFJSInterface.Profile = function() { this.prefixes = new RDFJSInterface.UrisMap(); this.terms = new RDFJSInterface.UrisMap(); - }; +}; - RDFJSInterface.Profile.prototype.importProfile = function(profile, override) { +RDFJSInterface.Profile.prototype.importProfile = function(profile, override) { this.prefixes.addAll(profile.prefixes, override); this.terms.addAll(profile.terms, override); - }; +}; - RDFJSInterface.Profile.prototype.resolve = function(toResolve) { +RDFJSInterface.Profile.prototype.resolve = function(toResolve) { if(toResolve.indexOf(":") != -1) { - return this.prefixes.resolve(toResolve); + return this.prefixes.resolve(toResolve); } else if(this.terms[toResolve] != null) { - return this.terms.resolve(toResolve); + return this.terms.resolve(toResolve); } else { - return null; + return null; } - }; +}; - RDFJSInterface.Profile.prototype.setDefaultPrefix = function(iri) { +RDFJSInterface.Profile.prototype.setDefaultPrefix = function(iri) { this.prefixes.setDefault(iri); - }; +}; - RDFJSInterface.Profile.prototype.setDefaultVocabulary = function(iri) { +RDFJSInterface.Profile.prototype.setDefaultVocabulary = function(iri) { this.terms.setDefault(iri); - }; +}; - RDFJSInterface.Profile.prototype.setPrefix = function(prefix, iri) { +RDFJSInterface.Profile.prototype.setPrefix = function(prefix, iri) { this.prefixes.set(prefix, iri); - }; +}; - RDFJSInterface.Profile.prototype.setTerm = function(term, iri) { +RDFJSInterface.Profile.prototype.setTerm = function(term, iri) { this.terms.set(term, iri); - }; +}; // RDF environemnt - RDFJSInterface.RDFEnvironment = function () { +RDFJSInterface.RDFEnvironment = function () { this.blankNodeCounter = 0; var that = this; this.filters = { - s:function (s) { - return function (t) { - return t.subject.equals(s); - }; - }, - p:function (p) { - return function (t) { - return t.predicate.equals(p); - }; - }, - o:function (o) { - return function (t) { - return t.object.equals(o); - }; - }, - sp:function (s, p) { - return function (t) { - return t.subject.equals(s) && t.predicate.equals(p); - }; - }, - so:function (s, o) { - return function (t) { - return t.subject.equals(s) && t.object.equals(o); - }; - }, - po:function (p, o) { - return function (t) { - return t.predicate.equals(p) && t.object.equals(o); - }; - }, - spo:function (s, p, o) { - return function (t) { - return t.subject.equals(s) && t.predicate.equals(p) && t.object.equals(o); - }; - }, - describes:function (v) { - return function (t) { - return t.subject.equals(v) || t.object.equals(v); - }; - }, - type:function (o) { - var type = that.resolve("rdf:type"); - return function (t) { - return t.predicate.equals(type) && t.object.equals(o); - }; - } + s:function (s) { + return function (t) { + return t.subject.equals(s); + }; + }, + p:function (p) { + return function (t) { + return t.predicate.equals(p); + }; + }, + o:function (o) { + return function (t) { + return t.object.equals(o); + }; + }, + sp:function (s, p) { + return function (t) { + return t.subject.equals(s) && t.predicate.equals(p); + }; + }, + so:function (s, o) { + return function (t) { + return t.subject.equals(s) && t.object.equals(o); + }; + }, + po:function (p, o) { + return function (t) { + return t.predicate.equals(p) && t.object.equals(o); + }; + }, + spo:function (s, p, o) { + return function (t) { + return t.subject.equals(s) && t.predicate.equals(p) && t.object.equals(o); + }; + }, + describes:function (v) { + return function (t) { + return t.subject.equals(v) || t.object.equals(v); + }; + }, + type:function (o) { + var type = that.resolve("rdf:type"); + return function (t) { + return t.predicate.equals(type) && t.object.equals(o); + }; + } }; for (var p in RDFJSInterface.defaultContext) { - this.prefixes.set(p, RDFJSInterface.defaultContext[p]); + this.prefixes.set(p, RDFJSInterface.defaultContext[p]); } - }; - Utils['extends'](RDFJSInterface.Profile,RDFJSInterface.RDFEnvironment); +}; +Utils['extends'](RDFJSInterface.Profile,RDFJSInterface.RDFEnvironment); - RDFJSInterface.RDFEnvironment.prototype.createBlankNode = function() { - var bnode = new RDFJSInterface.BlankNode(this.blankNodeCounter); +RDFJSInterface.RDFEnvironment.prototype.createBlankNode = function() { + var bnode = new RDFJSInterface.BlankNode(this.blankNodeCounter); this.blankNodeCounter++; return bnode; - }; +}; - RDFJSInterface.RDFEnvironment.prototype.createNamedNode = function(value) { +RDFJSInterface.RDFEnvironment.prototype.createNamedNode = function(value) { var resolvedValue = this.resolve(value); if(resolvedValue != null) { - return new RDFJSInterface.NamedNode(resolvedValue); + return new RDFJSInterface.NamedNode(resolvedValue); } else { - return new RDFJSInterface.NamedNode(value); + return new RDFJSInterface.NamedNode(value); } - }; +}; - RDFJSInterface.RDFEnvironment.prototype.createLiteral = function(value, language, datatype) { +RDFJSInterface.RDFEnvironment.prototype.createLiteral = function(value, language, datatype) { if(datatype != null) { - return new RDFJSInterface.Literal(value, language, datatype.toString()); + return new RDFJSInterface.Literal(value, language, datatype.toString()); } else { - return new RDFJSInterface.Literal(value, language, datatype); + return new RDFJSInterface.Literal(value, language, datatype); } - }; +}; - RDFJSInterface.RDFEnvironment.prototype.createTriple = function(subject, predicate, object) { +RDFJSInterface.RDFEnvironment.prototype.createTriple = function(subject, predicate, object) { return new RDFJSInterface.Triple(subject, predicate, object); - }; +}; - RDFJSInterface.RDFEnvironment.prototype.createGraph = function(triples) { +RDFJSInterface.RDFEnvironment.prototype.createGraph = function(triples) { var graph = new RDFJSInterface.Graph(); if(triples != null) { - for(var i=0; i"; + tmp = tmp + "^^<" + (this.datatype||this.type) + ">"; } return tmp; - }; +}; - RDFJSInterface.Literal.prototype.toNT = function() { +RDFJSInterface.Literal.prototype.toNT = function() { return this.toString(); - }; +}; - RDFJSInterface.Literal.prototype.valueOf = function() { - return QueryFilters.effectiveTypeValue({token: 'literal', - type: (this.type || this.datatype), - value: this.nominalValue, - language: this.language}); - }; +RDFJSInterface.Literal.prototype.valueOf = function() { + return QueryFilters.effectiveTypeValue({token: 'literal', + type: (this.type || this.datatype), + value: this.nominalValue, + language: this.language}); +}; // NamedNode node - RDFJSInterface.NamedNode = function(val) { +RDFJSInterface.NamedNode = function(val) { RDFJSInterface.RDFNode.call(this, "NamedNode"); if(val.value != null) { - this.nominalValue = val.value; + this.nominalValue = val.value; } else { - this.nominalValue = val; + this.nominalValue = val; } - }; +}; - Utils['extends'](RDFJSInterface.RDFNode,RDFJSInterface.NamedNode); +Utils['extends'](RDFJSInterface.RDFNode,RDFJSInterface.NamedNode); - RDFJSInterface.NamedNode.prototype.toString = function(){ +RDFJSInterface.NamedNode.prototype.toString = function(){ return this.nominalValue; - }; +}; - RDFJSInterface.NamedNode.prototype.toNT = function() { +RDFJSInterface.NamedNode.prototype.toNT = function() { return "<"+this.toString()+">"; - }; +}; - RDFJSInterface.NamedNode.prototype.valueOf = function() { +RDFJSInterface.NamedNode.prototype.valueOf = function() { return this.nominalValue; - }; +}; // Triple interface - RDFJSInterface.Triple = function(subject, predicate, object){ +RDFJSInterface.Triple = function(subject, predicate, object){ this.subject = subject; this.predicate = predicate; this.object = object; - }; +}; - RDFJSInterface.Triple.prototype.equals = function(otherTriple) { +RDFJSInterface.Triple.prototype.equals = function(otherTriple) { return this.subject.equals(otherTriple.subject) && - this.predicate.equals(otherTriple.predicate) && - this.object.equals(otherTriple.object); - }; + this.predicate.equals(otherTriple.predicate) && + this.object.equals(otherTriple.object); +}; - RDFJSInterface.Triple.prototype.toString = function() { +RDFJSInterface.Triple.prototype.toString = function() { return this.subject.toNT()+" "+this.predicate.toNT()+" "+this.object.toNT()+" . \r\n"; - }; +}; // Graph interface - RDFJSInterface.Graph = function() { +RDFJSInterface.Graph = function() { this.triples = []; this.duplicates = {}; this.actions = []; this.length = 0; - }; +}; - RDFJSInterface.Graph.prototype.add = function(triple) { +RDFJSInterface.Graph.prototype.add = function(triple) { for(var i=0; i true/false/error - var ebv = QueryFilters.ebv(ebv); - //console.log("EBV:") - //console.log(ebv) - //console.log("FOR:") - //console.log(thisDenormBindings) - if(QueryFilters.isEbvError(ebv)) { - // error - if(nullifyFilters) { - var thisBindings = {"__nullify__": true, "bindings": bindings[i]}; - filteredBindings.push(thisBindings); - } - } else if(ebv === true) { - // true - filteredBindings.push(bindings[i]); - } else { - // false - if(nullifyFilters) { - var thisBindings = {"__nullify__": true, "bindings": bindings[i]}; - filteredBindings.push(thisBindings); + var thisDenormBindings = denormBindings[i]; + var ebv = QueryFilters.runFilter(filterExpr, thisDenormBindings, queryEngine, dataset, env); + // ebv can be directly a RDFTerm (e.g. atomic expression in filter) + // this additional call to ebv will return -> true/false/error + var ebv = QueryFilters.ebv(ebv); + //console.log("EBV:") + //console.log(ebv) + //console.log("FOR:") + //console.log(thisDenormBindings) + if(QueryFilters.isEbvError(ebv)) { + // error + if(nullifyFilters) { + var thisBindings = {"__nullify__": true, "bindings": bindings[i]}; + filteredBindings.push(thisBindings); + } + } else if(ebv === true) { + // true + filteredBindings.push(bindings[i]); + } else { + // false + if(nullifyFilters) { + var thisBindings = {"__nullify__": true, "bindings": bindings[i]}; + filteredBindings.push(thisBindings); + } } - } } return filteredBindings; - }; +}; - QueryFilters.collect = function(filterExpr, bindings, dataset, env, queryEngine, callback) { +QueryFilters.collect = function(filterExpr, bindings, dataset, env, queryEngine, callback) { var denormBindings = queryEngine.copyDenormalizedBindings(bindings, env.outCache); var filteredBindings = []; for(var i=0; i') { - return QueryFilters.runGtFunction(op1, op2, bindings); + return QueryFilters.runGtFunction(op1, op2, bindings); } else if(operator === '<=') { - return QueryFilters.runLtEqFunction(op1, op2, bindings); + return QueryFilters.runLtEqFunction(op1, op2, bindings); } else if(operator === '>=') { - return QueryFilters.runGtEqFunction(op1, op2, bindings); + return QueryFilters.runGtEqFunction(op1, op2, bindings); } else { - throw("Error applying relational filter, unknown operator"); + throw("Error applying relational filter, unknown operator"); } - }; +}; - /** - * Transforms a JS object representing a [typed] literal in a javascript - * value that can be used in javascript operations and functions - */ - QueryFilters.effectiveTypeValue = function(val){ +/** + * Transforms a JS object representing a [typed] literal in a javascript + * value that can be used in javascript operations and functions + */ +QueryFilters.effectiveTypeValue = function(val){ if(val.token == 'literal') { - if(val.type == "http://www.w3.org/2001/XMLSchema#integer") { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if(val.type == "http://www.w3.org/2001/XMLSchema#decimal") { - var tmp = parseFloat(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#float") { - var tmp = parseFloat(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#double") { - var tmp = parseFloat(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#nonPositiveInteger") { - var tmp = parseFloat(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#negativeInteger") { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#long") { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#int") { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#short") { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#byte") { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#nonNegativeInteger") { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#unsignedLong") { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#unsignedInt") { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#unsignedShort") { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#unsignedByte") { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#positiveInteger" ) { - var tmp = parseInt(val.value); - //if(isNaN(tmp)) { - // return false; - //} else { - return tmp; - //} - } else if (val.type == "http://www.w3.org/2001/XMLSchema#date" || - val.type == "http://www.w3.org/2001/XMLSchema#dateTime" ) { - try { - var d = Utils.parseISO8601(val.value); - return(d); - } catch(e) { - return null; - } - } else if (val.type == "http://www.w3.org/2001/XMLSchema#boolean" ) { - return val.value === true || val.value === 'true' || val.value === '1' || val.value === 1 || val.value === true ? true : - val.value === false || val.value === 'false' || val.value === '0' || val.value === 0 || val.value === false ? false : - undefined; - } else if (val.type == "http://www.w3.org/2001/XMLSchema#string" ) { - return val.value === null || val.value === undefined ? undefined : ''+val.value; - } else if (val.type == null) { - // plain literal -> just manipulate the string - return val.value; - } else { - return val.value - } + if(val.type == "http://www.w3.org/2001/XMLSchema#integer") { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if(val.type == "http://www.w3.org/2001/XMLSchema#decimal") { + var tmp = parseFloat(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#float") { + var tmp = parseFloat(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#double") { + var tmp = parseFloat(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#nonPositiveInteger") { + var tmp = parseFloat(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#negativeInteger") { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#long") { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#int") { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#short") { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#byte") { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#nonNegativeInteger") { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#unsignedLong") { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#unsignedInt") { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#unsignedShort") { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#unsignedByte") { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#positiveInteger" ) { + var tmp = parseInt(val.value); + //if(isNaN(tmp)) { + // return false; + //} else { + return tmp; + //} + } else if (val.type == "http://www.w3.org/2001/XMLSchema#date" || + val.type == "http://www.w3.org/2001/XMLSchema#dateTime" ) { + try { + var d = Utils.parseISO8601(val.value); + return(d); + } catch(e) { + return null; + } + } else if (val.type == "http://www.w3.org/2001/XMLSchema#boolean" ) { + return val.value === true || val.value === 'true' || val.value === '1' || val.value === 1 || val.value === true ? true : + val.value === false || val.value === 'false' || val.value === '0' || val.value === 0 || val.value === false ? false : + undefined; + } else if (val.type == "http://www.w3.org/2001/XMLSchema#string" ) { + return val.value === null || val.value === undefined ? undefined : ''+val.value; + } else if (val.type == null) { + // plain literal -> just manipulate the string + return val.value; + } else { + return val.value + } } else { - // @todo - console.log("not implemented yet"); - console.log(val); - throw("value not supported in operations yet"); + // @todo + console.log("not implemented yet"); + console.log(val); + throw("value not supported in operations yet"); } - }; +}; - /* - A logical-or that encounters an error on only one branch will return TRUE if the other branch is TRUE and an error if the other branch is FALSE. - A logical-or or logical-and that encounters errors on both branches will produce either of the errors. - */ - QueryFilters.runOrFunction = function(filterExpr, bindings, queryEngine, dataset, env) { +/* + A logical-or that encounters an error on only one branch will return TRUE if the other branch is TRUE and an error if the other branch is FALSE. + A logical-or or logical-and that encounters errors on both branches will produce either of the errors. +*/ +QueryFilters.runOrFunction = function(filterExpr, bindings, queryEngine, dataset, env) { var acum = null; for(var i=0; i< filterExpr.operands.length; i++) { - var ebv = QueryFilters.runFilter(filterExpr.operands[i], bindings, queryEngine, dataset, env); - if(QueryFilters.isEbvError(ebv) == false) { - ebv = QueryFilters.ebv(ebv); - } - if(acum == null) { - acum = ebv; - } else if(QueryFilters.isEbvError(ebv)) { - if(QueryFilters.isEbvError(acum)) { - acum = QueryFilters.ebvError(); - } else if(acum === true) { - acum = true; - } else { - acum = QueryFilters.ebvError(); - } - } else if(ebv === true) { - acum = true; - } else { - if(QueryFilters.isEbvError(acum)) { - acum = QueryFilters.ebvError(); + var ebv = QueryFilters.runFilter(filterExpr.operands[i], bindings, queryEngine, dataset, env); + if(QueryFilters.isEbvError(ebv) == false) { + ebv = QueryFilters.ebv(ebv); + } + if(acum == null) { + acum = ebv; + } else if(QueryFilters.isEbvError(ebv)) { + if(QueryFilters.isEbvError(acum)) { + acum = QueryFilters.ebvError(); + } else if(acum === true) { + acum = true; + } else { + acum = QueryFilters.ebvError(); + } + } else if(ebv === true) { + acum = true; + } else { + if(QueryFilters.isEbvError(acum)) { + acum = QueryFilters.ebvError(); + } } - } } return QueryFilters.ebvBoolean(acum); - }; +}; - /* - A logical-and that encounters an error on only one branch will return an error if the other branch is TRUE and FALSE if the other branch is FALSE. - A logical-or or logical-and that encounters errors on both branches will produce either of the errors. - */ - QueryFilters.runAndFunction = function(filterExpr, bindings, queryEngine, dataset, env) { +/* + A logical-and that encounters an error on only one branch will return an error if the other branch is TRUE and FALSE if the other branch is FALSE. + A logical-or or logical-and that encounters errors on both branches will produce either of the errors. +*/ +QueryFilters.runAndFunction = function(filterExpr, bindings, queryEngine, dataset, env) { var acum = null; for(var i=0; i< filterExpr.operands.length; i++) { - var ebv = QueryFilters.runFilter(filterExpr.operands[i], bindings, queryEngine, dataset, env); + var ebv = QueryFilters.runFilter(filterExpr.operands[i], bindings, queryEngine, dataset, env); - if(QueryFilters.isEbvError(ebv) == false) { - ebv = QueryFilters.ebv(ebv); - } + if(QueryFilters.isEbvError(ebv) == false) { + ebv = QueryFilters.ebv(ebv); + } - if(acum == null) { - acum = ebv; - } else if(QueryFilters.isEbvError(ebv)) { - if(QueryFilters.isEbvError(acum)) { - acum = QueryFilters.ebvError(); - } else if(acum === true) { - acum = QueryFilters.ebvError(); + if(acum == null) { + acum = ebv; + } else if(QueryFilters.isEbvError(ebv)) { + if(QueryFilters.isEbvError(acum)) { + acum = QueryFilters.ebvError(); + } else if(acum === true) { + acum = QueryFilters.ebvError(); + } else { + acum = false; + } + } else if(ebv === true) { + if(QueryFilters.isEbvError(acum)) { + acum = QueryFilters.ebvError(); + } } else { - acum = false; - } - } else if(ebv === true) { - if(QueryFilters.isEbvError(acum)) { - acum = QueryFilters.ebvError(); + acum = false; } - } else { - acum = false; - } } return QueryFilters.ebvBoolean(acum); - }; +}; - QueryFilters.runEqualityFunction = function(op1, op2, bindings, queryEngine, dataset, env) { +QueryFilters.runEqualityFunction = function(op1, op2, bindings, queryEngine, dataset, env) { if(QueryFilters.isEbvError(op1) || QueryFilters.isEbvError(op2)) { - return QueryFilters.ebvError(); + return QueryFilters.ebvError(); } if(QueryFilters.isNumeric(op1) && QueryFilters.isNumeric(op2)) { - var eop1 = QueryFilters.effectiveTypeValue(op1); - var eop2 = QueryFilters.effectiveTypeValue(op2); - if(isNaN(eop1) || isNaN(eop2)) { - return QueryFilters.ebvBoolean(QueryFilters.RDFTermEquality(op1, op2, queryEngine, env)); - } else { - return QueryFilters.ebvBoolean(eop1 == eop2); - } - } else if((QueryFilters.isSimpleLiteral(op1) || QueryFilters.isXsdType("string", op1)) && - (QueryFilters.isSimpleLiteral(op2) || QueryFilters.isXsdType("string", op2))) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) == QueryFilters.effectiveTypeValue(op2)); + var eop1 = QueryFilters.effectiveTypeValue(op1); + var eop2 = QueryFilters.effectiveTypeValue(op2); + if(isNaN(eop1) || isNaN(eop2)) { + return QueryFilters.ebvBoolean(QueryFilters.RDFTermEquality(op1, op2, queryEngine, env)); + } else { + return QueryFilters.ebvBoolean(eop1 == eop2); + } + } else if((QueryFilters.isSimpleLiteral(op1) || QueryFilters.isXsdType("string", op1)) && + (QueryFilters.isSimpleLiteral(op2) || QueryFilters.isXsdType("string", op2))) { + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) == QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isXsdType("boolean", op1) && QueryFilters.isXsdType("boolean", op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) == QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) == QueryFilters.effectiveTypeValue(op2)); } else if((QueryFilters.isXsdType("dateTime", op1)||QueryFilters.isXsdType("date", op1)) && (QueryFilters.isXsdType("dateTime", op2)||QueryFilters.isXsdType("date", op2))) { - if(QueryFilters.isXsdType("dateTime", op1) && QueryFilters.isXsdType("date", op2)) { - return QueryFilters.ebvFalse(); - } - if(QueryFilters.isXsdType("date", op1) && QueryFilters.isXsdType("dateTime", op2)) { - return QueryFilters.ebvFalse(); - } + if(QueryFilters.isXsdType("dateTime", op1) && QueryFilters.isXsdType("date", op2)) { + return QueryFilters.ebvFalse(); + } + if(QueryFilters.isXsdType("date", op1) && QueryFilters.isXsdType("dateTime", op2)) { + return QueryFilters.ebvFalse(); + } - var comp = Utils.compareDateComponents(op1.value, op2.value); - if(comp != null) { - if(comp == 0) { - return QueryFilters.ebvTrue(); + var comp = Utils.compareDateComponents(op1.value, op2.value); + if(comp != null) { + if(comp == 0) { + return QueryFilters.ebvTrue(); + } else { + return QueryFilters.ebvFalse(); + } } else { - return QueryFilters.ebvFalse(); + return QueryFilters.ebvError(); } - } else { - return QueryFilters.ebvError(); - } } else if(QueryFilters.isRDFTerm(op1) && QueryFilters.isRDFTerm(op2)) { - return QueryFilters.ebvBoolean(QueryFilters.RDFTermEquality(op1, op2, queryEngine, env)); + return QueryFilters.ebvBoolean(QueryFilters.RDFTermEquality(op1, op2, queryEngine, env)); } else { - return QueryFilters.ebvFalse(); + return QueryFilters.ebvFalse(); } - }; +}; - QueryFilters.runGtFunction = function(op1, op2, bindings) { +QueryFilters.runGtFunction = function(op1, op2, bindings) { if(QueryFilters.isEbvError(op1) || QueryFilters.isEbvError(op2)) { - return QueryFilters.ebvError(); + return QueryFilters.ebvError(); } if(QueryFilters.isNumeric(op1) && QueryFilters.isNumeric(op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) > QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) > QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isSimpleLiteral(op1) && QueryFilters.isSimpleLiteral(op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) > QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) > QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isXsdType("string", op1) && QueryFilters.isXsdType("string", op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) > QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) > QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isXsdType("boolean", op1) && QueryFilters.isXsdType("boolean", op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) > QueryFilters.effectiveTypeValue(op2)); - } else if((QueryFilters.isXsdType("dateTime", op1) || QueryFilters.isXsdType("date", op1)) && - (QueryFilters.isXsdType("dateTime", op2) || QueryFilters.isXsdType("date", op2))) { - if(QueryFilters.isXsdType("dateTime", op1) && QueryFilters.isXsdType("date", op2)) { - return QueryFilters.ebvFalse(); - } - if(QueryFilters.isXsdType("date", op1) && QueryFilters.isXsdType("dateTime", op2)) { - return QueryFilters.ebvFalse(); - } + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) > QueryFilters.effectiveTypeValue(op2)); + } else if((QueryFilters.isXsdType("dateTime", op1) || QueryFilters.isXsdType("date", op1)) && + (QueryFilters.isXsdType("dateTime", op2) || QueryFilters.isXsdType("date", op2))) { + if(QueryFilters.isXsdType("dateTime", op1) && QueryFilters.isXsdType("date", op2)) { + return QueryFilters.ebvFalse(); + } + if(QueryFilters.isXsdType("date", op1) && QueryFilters.isXsdType("dateTime", op2)) { + return QueryFilters.ebvFalse(); + } - var comp = Utils.compareDateComponents(op1.value, op2.value); - if(comp != null) { - if(comp == 1) { - return QueryFilters.ebvTrue(); + var comp = Utils.compareDateComponents(op1.value, op2.value); + if(comp != null) { + if(comp == 1) { + return QueryFilters.ebvTrue(); + } else { + return QueryFilters.ebvFalse(); + } } else { - return QueryFilters.ebvFalse(); + return QueryFilters.ebvError(); } - } else { - return QueryFilters.ebvError(); - } } else { - return QueryFilters.ebvFalse(); + return QueryFilters.ebvFalse(); } - }; +}; - /** - * Total gt function used when sorting bindings in the SORT BY clause. - * - * @todo - * Some criteria are not clear - */ - QueryFilters.runTotalGtFunction = function(op1,op2) { +/** + * Total gt function used when sorting bindings in the SORT BY clause. + * + * @todo + * Some criteria are not clear + */ +QueryFilters.runTotalGtFunction = function(op1,op2) { if(QueryFilters.isEbvError(op1) || QueryFilters.isEbvError(op2)) { - return QueryFilters.ebvError(); + return QueryFilters.ebvError(); } if((QueryFilters.isNumeric(op1) && QueryFilters.isNumeric(op2)) || - (QueryFilters.isSimpleLiteral(op1) && QueryFilters.isSimpleLiteral(op2)) || - (QueryFilters.isXsdType("string",op1) && QueryFilters.isSimpleLiteral("string",op2)) || - (QueryFilters.isXsdType("boolean",op1) && QueryFilters.isSimpleLiteral("boolean",op2)) || - (QueryFilters.isXsdType("dateTime",op1) && QueryFilters.isSimpleLiteral("dateTime",op2))) { - return QueryFilters.runGtFunction(op1, op2, []); + (QueryFilters.isSimpleLiteral(op1) && QueryFilters.isSimpleLiteral(op2)) || + (QueryFilters.isXsdType("string",op1) && QueryFilters.isSimpleLiteral("string",op2)) || + (QueryFilters.isXsdType("boolean",op1) && QueryFilters.isSimpleLiteral("boolean",op2)) || + (QueryFilters.isXsdType("dateTime",op1) && QueryFilters.isSimpleLiteral("dateTime",op2))) { + return QueryFilters.runGtFunction(op1, op2, []); } else if(op1.token && op1.token === 'uri' && op2.token && op2.token === 'uri') { - return QueryFilters.ebvBoolean(op1.value > op2.value); + return QueryFilters.ebvBoolean(op1.value > op2.value); } else if(op1.token && op1.token === 'literal' && op2.token && op2.token === 'literal') { - // one of the literals must have type/lang and the othe may not have them - return QueryFilters.ebvBoolean(""+op1.value+op1.type+op1.lang > ""+op2.value+op2.type+op2.lang); - } else if(op1.token && op1.token === 'blank' && op2.token && op2.token === 'blank') { - return QueryFilters.ebvBoolean(op1.value > op2.value); + // one of the literals must have type/lang and the othe may not have them + return QueryFilters.ebvBoolean(""+op1.value+op1.type+op1.lang > ""+op2.value+op2.type+op2.lang); + } else if(op1.token && op1.token === 'blank' && op2.token && op2.token === 'blank') { + return QueryFilters.ebvBoolean(op1.value > op2.value); } else if(op1.value && op2.value) { - return QueryFilters.ebvBoolean(op1.value > op2.value); + return QueryFilters.ebvBoolean(op1.value > op2.value); } else { - return QueryFilters.ebvTrue(); + return QueryFilters.ebvTrue(); } - }; +}; - QueryFilters.runLtFunction = function(op1, op2, bindings) { +QueryFilters.runLtFunction = function(op1, op2, bindings) { if(QueryFilters.isEbvError(op1) || QueryFilters.isEbvError(op2)) { - return QueryFilters.ebvError(); + return QueryFilters.ebvError(); } if(QueryFilters.isNumeric(op1) && QueryFilters.isNumeric(op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) < QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) < QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isSimpleLiteral(op1) && QueryFilters.isSimpleLiteral(op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) < QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) < QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isXsdType("string", op1) && QueryFilters.isXsdType("string", op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) < QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) < QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isXsdType("boolean", op1) && QueryFilters.isXsdType("boolean", op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) < QueryFilters.effectiveTypeValue(op2)); - } else if((QueryFilters.isXsdType("dateTime", op1) || QueryFilters.isXsdType("date", op1)) && - (QueryFilters.isXsdType("dateTime", op2) || QueryFilters.isXsdType("date", op2))) { - if(QueryFilters.isXsdType("dateTime", op1) && QueryFilters.isXsdType("date", op2)) { - return QueryFilters.ebvFalse(); - } - if(QueryFilters.isXsdType("date", op1) && QueryFilters.isXsdType("dateTime", op2)) { - return QueryFilters.ebvFalse(); - } + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) < QueryFilters.effectiveTypeValue(op2)); + } else if((QueryFilters.isXsdType("dateTime", op1) || QueryFilters.isXsdType("date", op1)) && + (QueryFilters.isXsdType("dateTime", op2) || QueryFilters.isXsdType("date", op2))) { + if(QueryFilters.isXsdType("dateTime", op1) && QueryFilters.isXsdType("date", op2)) { + return QueryFilters.ebvFalse(); + } + if(QueryFilters.isXsdType("date", op1) && QueryFilters.isXsdType("dateTime", op2)) { + return QueryFilters.ebvFalse(); + } - var comp = Utils.compareDateComponents(op1.value, op2.value); - if(comp != null) { - if(comp == -1) { - return QueryFilters.ebvTrue(); + var comp = Utils.compareDateComponents(op1.value, op2.value); + if(comp != null) { + if(comp == -1) { + return QueryFilters.ebvTrue(); + } else { + return QueryFilters.ebvFalse(); + } } else { - return QueryFilters.ebvFalse(); + return QueryFilters.ebvError(); } - } else { - return QueryFilters.ebvError(); - } } else { - return QueryFilters.ebvFalse(); + return QueryFilters.ebvFalse(); } - }; +}; - QueryFilters.runGtEqFunction = function(op1, op2, bindings) { +QueryFilters.runGtEqFunction = function(op1, op2, bindings) { if(QueryFilters.isEbvError(op1) || QueryFilters.isEbvError(op2)) { - return QueryFilters.ebvError(); + return QueryFilters.ebvError(); } if(QueryFilters.isNumeric(op1) && QueryFilters.isNumeric(op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) >= QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) >= QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isSimpleLiteral(op1) && QueryFilters.isSimpleLiteral(op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) >= QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) >= QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isXsdType("string", op1) && QueryFilters.isXsdType("string", op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) >= QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) >= QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isXsdType("boolean", op1) && QueryFilters.isXsdType("boolean", op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) >= QueryFilters.effectiveTypeValue(op2)); - } else if((QueryFilters.isXsdType("dateTime", op1) || QueryFilters.isXsdType("date", op1)) && - (QueryFilters.isXsdType("dateTime", op2) || QueryFilters.isXsdType("date", op2))) { - if(QueryFilters.isXsdType("dateTime", op1) && QueryFilters.isXsdType("date", op2)) { - return QueryFilters.ebvFalse(); - } - if(QueryFilters.isXsdType("date", op1) && QueryFilters.isXsdType("dateTime", op2)) { - return QueryFilters.ebvFalse(); - } + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) >= QueryFilters.effectiveTypeValue(op2)); + } else if((QueryFilters.isXsdType("dateTime", op1) || QueryFilters.isXsdType("date", op1)) && + (QueryFilters.isXsdType("dateTime", op2) || QueryFilters.isXsdType("date", op2))) { + if(QueryFilters.isXsdType("dateTime", op1) && QueryFilters.isXsdType("date", op2)) { + return QueryFilters.ebvFalse(); + } + if(QueryFilters.isXsdType("date", op1) && QueryFilters.isXsdType("dateTime", op2)) { + return QueryFilters.ebvFalse(); + } - var comp = Utils.compareDateComponents(op1.value, op2.value); - if(comp != null) { - if(comp != -1) { - return QueryFilters.ebvTrue(); + var comp = Utils.compareDateComponents(op1.value, op2.value); + if(comp != null) { + if(comp != -1) { + return QueryFilters.ebvTrue(); + } else { + return QueryFilters.ebvFalse(); + } } else { - return QueryFilters.ebvFalse(); + return QueryFilters.ebvError(); } - } else { - return QueryFilters.ebvError(); - } } else { - return QueryFilters.ebvFalse(); + return QueryFilters.ebvFalse(); } - }; +}; - QueryFilters.runLtEqFunction = function(op1, op2, bindings) { +QueryFilters.runLtEqFunction = function(op1, op2, bindings) { if(QueryFilters.isEbvError(op1) || QueryFilters.isEbvError(op2)) { - return QueryFilters.ebvError(); + return QueryFilters.ebvError(); } if(QueryFilters.isNumeric(op1) && QueryFilters.isNumeric(op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) <= QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) <= QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isSimpleLiteral(op1) && QueryFilters.isSimpleLiteral(op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) <= QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) <= QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isXsdType("string", op1) && QueryFilters.isXsdType("string", op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) <= QueryFilters.effectiveTypeValue(op2)); + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) <= QueryFilters.effectiveTypeValue(op2)); } else if(QueryFilters.isXsdType("boolean", op1) && QueryFilters.isXsdType("boolean", op2)) { - return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) <= QueryFilters.effectiveTypeValue(op2)); - } else if((QueryFilters.isXsdType("dateTime", op1) || QueryFilters.isXsdType("date", op1)) && - (QueryFilters.isXsdType("dateTime", op2) || QueryFilters.isXsdType("date", op2))) { - if(QueryFilters.isXsdType("dateTime", op1) && QueryFilters.isXsdType("date", op2)) { - return QueryFilters.ebvFalse(); - } - if(QueryFilters.isXsdType("date", op1) && QueryFilters.isXsdType("dateTime", op2)) { - return QueryFilters.ebvFalse(); - } + return QueryFilters.ebvBoolean(QueryFilters.effectiveTypeValue(op1) <= QueryFilters.effectiveTypeValue(op2)); + } else if((QueryFilters.isXsdType("dateTime", op1) || QueryFilters.isXsdType("date", op1)) && + (QueryFilters.isXsdType("dateTime", op2) || QueryFilters.isXsdType("date", op2))) { + if(QueryFilters.isXsdType("dateTime", op1) && QueryFilters.isXsdType("date", op2)) { + return QueryFilters.ebvFalse(); + } + if(QueryFilters.isXsdType("date", op1) && QueryFilters.isXsdType("dateTime", op2)) { + return QueryFilters.ebvFalse(); + } - var comp = Utils.compareDateComponents(op1.value, op2.value); - if(comp != null) { - if(comp != 1) { - return QueryFilters.ebvTrue(); + var comp = Utils.compareDateComponents(op1.value, op2.value); + if(comp != null) { + if(comp != 1) { + return QueryFilters.ebvTrue(); + } else { + return QueryFilters.ebvFalse(); + } } else { - return QueryFilters.ebvFalse(); + return QueryFilters.ebvError(); } - } else { - return QueryFilters.ebvError(); - } } else { - return QueryFilters.ebvFalse(); + return QueryFilters.ebvFalse(); } - }; +}; - QueryFilters.runAddition = function(summand, summands, bindings, queryEngine, dataset, env) { +QueryFilters.runAddition = function(summand, summands, bindings, queryEngine, dataset, env) { var summandOp = QueryFilters.runFilter(summand,bindings,queryEngine, dataset, env); if(QueryFilters.isEbvError(summandOp)) { - return QueryFilters.ebvError(); + return QueryFilters.ebvError(); } var acum = summandOp; if(QueryFilters.isNumeric(summandOp)) { - for(var i=0; i 2) { - return QueryFilters.ebvError(); - } else if (from.value.split("-").length > 2) { - return QueryFilters.ebvError(); - } else if (from.value.split("/").length > 2) { - return QueryFilters.ebvError(); - } else if (from.value.split("+").length > 2) { - return QueryFilters.ebvError(); - } - - // @todo improve this with regular expressions for each lexical representation - if(fun == "http://www.w3.org/2001/XMLSchema#decimal") { - if(from.value.indexOf("e") != -1 || from.value.indexOf("E") != -1) { - return QueryFilters.ebvError(); - } - } + var ops = []; + for(var i=0; i 2) { + return QueryFilters.ebvError(); + } else if (from.value.split("-").length > 2) { + return QueryFilters.ebvError(); + } else if (from.value.split("/").length > 2) { + return QueryFilters.ebvError(); + } else if (from.value.split("+").length > 2) { + return QueryFilters.ebvError(); + } - // @todo improve this with regular expressions for each lexical representation - if(fun == "http://www.w3.org/2001/XMLSchema#int" || fun == "http://www.w3.org/2001/XMLSchema#integer") { - if(from.value.indexOf("e") != -1 || from.value.indexOf("E") != -1 || from.value.indexOf(".") != -1) { - return QueryFilters.ebvError(); - } - } + // @todo improve this with regular expressions for each lexical representation + if(fun == "http://www.w3.org/2001/XMLSchema#decimal") { + if(from.value.indexOf("e") != -1 || from.value.indexOf("E") != -1) { + return QueryFilters.ebvError(); + } + } - try { - from.value = parseInt(parseFloat(from.value)); - if(isNaN(from.value)) { + // @todo improve this with regular expressions for each lexical representation + if(fun == "http://www.w3.org/2001/XMLSchema#int" || fun == "http://www.w3.org/2001/XMLSchema#integer") { + if(from.value.indexOf("e") != -1 || from.value.indexOf("E") != -1 || from.value.indexOf(".") != -1) { + return QueryFilters.ebvError(); + } + } + + try { + from.value = parseInt(parseFloat(from.value)); + if(isNaN(from.value)) { + return QueryFilters.ebvError(); + } else { + from.type = fun; + return from; + } + } catch(e) { + return QueryFilters.ebvError(); + } + } else { + return QueryFilters.ebvError(); + } + } else { return QueryFilters.ebvError(); + } + } else if(fun == "http://www.w3.org/2001/XMLSchema#boolean") { + var from = ops[0]; + if(from.token === "literal" && from.type == null) { + if(from.value === "true" || from.value === "1") { + return QueryFilters.ebvTrue(); + } else if(from.value === "false" || from.value === "0" ) { + return QueryFilters.ebvFalse(); + } else { + return QueryFilters.ebvError(); + } + } else if(from.token === "literal") { + if(QueryFilters.isEbvError(from)) { + return from; } else { - from.type = fun; - return from; + return QueryFilters.ebvBoolean(from); } - } catch(e) { - return QueryFilters.ebvError(); + } else { + return QueryFilters.ebvError(); } - } else { - return QueryFilters.ebvError(); - } - } else { - return QueryFilters.ebvError(); - } - } else if(fun == "http://www.w3.org/2001/XMLSchema#boolean") { - var from = ops[0]; - if(from.token === "literal" && from.type == null) { - if(from.value === "true" || from.value === "1") { - return QueryFilters.ebvTrue(); - } else if(from.value === "false" || from.value === "0" ) { - return QueryFilters.ebvFalse(); - } else { - return QueryFilters.ebvError(); - } - } else if(from.token === "literal") { - if(QueryFilters.isEbvError(from)) { - return from; - } else { - return QueryFilters.ebvBoolean(from); - } - } else { - return QueryFilters.ebvError(); - } - } else if(fun == "http://www.w3.org/2001/XMLSchema#string") { - var from = ops[0]; - if(from.token === 'literal') { - from = QueryFilters.normalizeLiteralDatatype(from, queryEngine, env); - if(from.type == "http://www.w3.org/2001/XMLSchema#integer" || - from.type == "http://www.w3.org/2001/XMLSchema#decimal" || - from.type == "http://www.w3.org/2001/XMLSchema#double" || - from.type == "http://www.w3.org/2001/XMLSchema#nonPositiveInteger" || - from.type == "http://www.w3.org/2001/XMLSchema#negativeInteger" || - from.type == "http://www.w3.org/2001/XMLSchema#long" || - from.type == "http://www.w3.org/2001/XMLSchema#int" || - from.type == "http://www.w3.org/2001/XMLSchema#short" || - from.type == "http://www.w3.org/2001/XMLSchema#byte" || - from.type == "http://www.w3.org/2001/XMLSchema#nonNegativeInteger" || - from.type == "http://www.w3.org/2001/XMLSchema#unsignedLong" || - from.type == "http://www.w3.org/2001/XMLSchema#unsignedInt" || - from.type == "http://www.w3.org/2001/XMLSchema#unsignedShort" || - from.type == "http://www.w3.org/2001/XMLSchema#unsignedByte" || - from.type == "http://www.w3.org/2001/XMLSchema#positiveInteger" || - from.type == "http://www.w3.org/2001/XMLSchema#float") { - from.type = fun; - from.value = ""+from.value; - return from; - } else if(from.type == "http://www.w3.org/2001/XMLSchema#string") { - return from; - } else if(from.type == "http://www.w3.org/2001/XMLSchema#boolean") { - if(QueryFilters.ebv(from)) { - from.type = fun; - from.value = 'true'; - } else { - from.type = fun; - from.value = 'false'; - } - return from; - } else if(from.type == "http://www.w3.org/2001/XMLSchema#dateTime" || - from.type == "http://www.w3.org/2001/XMLSchema#date") { - from.type = fun; - if(typeof(from.value) != 'string') { - from.value = Utils.iso8601(from.value); - } - return from; - } else if(from.type == null) { - from.value = ""+from.value; - from.type = fun; - return from; - } else { - return QueryFilters.ebvError(); - } - } else if(from.token === 'uri') { - return {token: 'literal', - value: Utils.lexicalFormBaseUri(from, env), - type: fun, - lang: null}; - } else { - return QueryFilters.ebvError(); - } - } else if(fun == "http://www.w3.org/2001/XMLSchema#dateTime" || fun == "http://www.w3.org/2001/XMLSchema#date") { - from = ops[0]; - if(from.type == "http://www.w3.org/2001/XMLSchema#dateTime" || from.type == "http://www.w3.org/2001/XMLSchema#date") { - return from; - } else if(from.type == "http://www.w3.org/2001/XMLSchema#string" || from.type == null) { - try { - from.value = Utils.iso8601(Utils.parseStrictISO8601(from.value)); - from.type = fun; - return from; - } catch(e) { - return QueryFilters.ebvError(); - } - } else { - return QueryFilters.ebvError(); - } - } else if(fun == "http://www.w3.org/2001/XMLSchema#float") { - var from = ops[0]; - if(from.token === 'literal') { - from = QueryFilters.normalizeLiteralDatatype(from, queryEngine, env); - if(from.type == 'http://www.w3.org/2001/XMLSchema#decimal' || - from.type == 'http://www.w3.org/2001/XMLSchema#int') { - from.type = fun; - from.value = parseFloat(from.value); - return from; - } else if(from.type == 'http://www.w3.org/2001/XMLSchema#boolean') { - if(QueryFilters.ebv(from) == true) { - from.type = fun; - from.value = 1.0; - } else { - from.type = fun; - from.value = 0.0; - } - return from; - } else if(from.type == 'http://www.w3.org/2001/XMLSchema#float' || - from.type == 'http://www.w3.org/2001/XMLSchema#double') { - from.type = fun; - from.value = parseFloat(from.value); - return from; - } else if(from.type == 'http://www.w3.org/2001/XMLSchema#string') { - try { - from.value = parseFloat(from.value); - if(isNaN(from.value)) { + } else if(fun == "http://www.w3.org/2001/XMLSchema#string") { + var from = ops[0]; + if(from.token === 'literal') { + from = QueryFilters.normalizeLiteralDatatype(from, queryEngine, env); + if(from.type == "http://www.w3.org/2001/XMLSchema#integer" || + from.type == "http://www.w3.org/2001/XMLSchema#decimal" || + from.type == "http://www.w3.org/2001/XMLSchema#double" || + from.type == "http://www.w3.org/2001/XMLSchema#nonPositiveInteger" || + from.type == "http://www.w3.org/2001/XMLSchema#negativeInteger" || + from.type == "http://www.w3.org/2001/XMLSchema#long" || + from.type == "http://www.w3.org/2001/XMLSchema#int" || + from.type == "http://www.w3.org/2001/XMLSchema#short" || + from.type == "http://www.w3.org/2001/XMLSchema#byte" || + from.type == "http://www.w3.org/2001/XMLSchema#nonNegativeInteger" || + from.type == "http://www.w3.org/2001/XMLSchema#unsignedLong" || + from.type == "http://www.w3.org/2001/XMLSchema#unsignedInt" || + from.type == "http://www.w3.org/2001/XMLSchema#unsignedShort" || + from.type == "http://www.w3.org/2001/XMLSchema#unsignedByte" || + from.type == "http://www.w3.org/2001/XMLSchema#positiveInteger" || + from.type == "http://www.w3.org/2001/XMLSchema#float") { + from.type = fun; + from.value = ""+from.value; + return from; + } else if(from.type == "http://www.w3.org/2001/XMLSchema#string") { + return from; + } else if(from.type == "http://www.w3.org/2001/XMLSchema#boolean") { + if(QueryFilters.ebv(from)) { + from.type = fun; + from.value = 'true'; + } else { + from.type = fun; + from.value = 'false'; + } + return from; + } else if(from.type == "http://www.w3.org/2001/XMLSchema#dateTime" || + from.type == "http://www.w3.org/2001/XMLSchema#date") { + from.type = fun; + if(typeof(from.value) != 'string') { + from.value = Utils.iso8601(from.value); + } + return from; + } else if(from.type == null) { + from.value = ""+from.value; + from.type = fun; + return from; + } else { + return QueryFilters.ebvError(); + } + } else if(from.token === 'uri') { + return {token: 'literal', + value: Utils.lexicalFormBaseUri(from, env), + type: fun, + lang: null}; + } else { return QueryFilters.ebvError(); - } else { - from.type = fun; + } + } else if(fun == "http://www.w3.org/2001/XMLSchema#dateTime" || fun == "http://www.w3.org/2001/XMLSchema#date") { + from = ops[0]; + if(from.type == "http://www.w3.org/2001/XMLSchema#dateTime" || from.type == "http://www.w3.org/2001/XMLSchema#date") { return from; - } - } catch(e) { - return QueryFilters.ebvError(); - } - } else if(from.type == null) { - // checking some exceptions that are parsed as Floats by JS - if(from.value.split(".").length > 2) { - return QueryFilters.ebvError(); - } else if (from.value.split("-").length > 2) { - return QueryFilters.ebvError(); - } else if (from.value.split("/").length > 2) { - return QueryFilters.ebvError(); - } else if (from.value.split("+").length > 2) { - return QueryFilters.ebvError(); + } else if(from.type == "http://www.w3.org/2001/XMLSchema#string" || from.type == null) { + try { + from.value = Utils.iso8601(Utils.parseStrictISO8601(from.value)); + from.type = fun; + return from; + } catch(e) { + return QueryFilters.ebvError(); + } + } else { + return QueryFilters.ebvError(); } + } else if(fun == "http://www.w3.org/2001/XMLSchema#float") { + var from = ops[0]; + if(from.token === 'literal') { + from = QueryFilters.normalizeLiteralDatatype(from, queryEngine, env); + if(from.type == 'http://www.w3.org/2001/XMLSchema#decimal' || + from.type == 'http://www.w3.org/2001/XMLSchema#int') { + from.type = fun; + from.value = parseFloat(from.value); + return from; + } else if(from.type == 'http://www.w3.org/2001/XMLSchema#boolean') { + if(QueryFilters.ebv(from) == true) { + from.type = fun; + from.value = 1.0; + } else { + from.type = fun; + from.value = 0.0; + } + return from; + } else if(from.type == 'http://www.w3.org/2001/XMLSchema#float' || + from.type == 'http://www.w3.org/2001/XMLSchema#double') { + from.type = fun; + from.value = parseFloat(from.value); + return from; + } else if(from.type == 'http://www.w3.org/2001/XMLSchema#string') { + try { + from.value = parseFloat(from.value); + if(isNaN(from.value)) { + return QueryFilters.ebvError(); + } else { + from.type = fun; + return from; + } + } catch(e) { + return QueryFilters.ebvError(); + } + } else if(from.type == null) { + // checking some exceptions that are parsed as Floats by JS + if(from.value.split(".").length > 2) { + return QueryFilters.ebvError(); + } else if (from.value.split("-").length > 2) { + return QueryFilters.ebvError(); + } else if (from.value.split("/").length > 2) { + return QueryFilters.ebvError(); + } else if (from.value.split("+").length > 2) { + return QueryFilters.ebvError(); + } - try { - from.value = parseFloat(from.value); - if(isNaN(from.value)) { + try { + from.value = parseFloat(from.value); + if(isNaN(from.value)) { + return QueryFilters.ebvError(); + } else { + from.type = fun; + return from; + } + } catch(e) { + return QueryFilters.ebvError(); + } + } else { + return QueryFilters.ebvError(); + } + } else { return QueryFilters.ebvError(); - } else { - from.type = fun; - return from; - } - } catch(e) { - return QueryFilters.ebvError(); } - } else { - return QueryFilters.ebvError(); - } } else { - return QueryFilters.ebvError(); + // unknown function + return QueryFilters.ebvError(); } - } else { - // unknown function - return QueryFilters.ebvError(); - } } - }; +}; // end of ./src/js-query-engine/src/query_filters.js // exports - var QueryPlanDPSize = {}; +var QueryPlanDPSize = {}; - QueryPlanDPSize.variablesInBGP = function(bgp) { +QueryPlanDPSize.variablesInBGP = function(bgp) { // may be cached in the pattern var variables = bgp.variables; if(variables) { - return variables; + return variables; } var components = bgp.value || bgp; variables = []; for(var comp in components) { - if(components[comp] && components[comp].token === "var") { - variables.push(components[comp].value); - } else if(components[comp] && components[comp].token === "blank") { - variables.push("blank:"+components[comp].value); - } + if(components[comp] && components[comp].token === "var") { + variables.push(components[comp].value); + } else if(components[comp] && components[comp].token === "blank") { + variables.push("blank:"+components[comp].value); + } } bgp.variables = variables; return variables; - }; +}; - QueryPlanDPSize.connected = function(leftPlan, rightPlan) { +QueryPlanDPSize.connected = function(leftPlan, rightPlan) { var varsLeft ="/"+leftPlan.vars.join("/")+"/"; for(var i=0; i0 - } + if(idsRight[i]=="") + continue; + if(leftPlan.i.indexOf('_'+idsRight[i]+'_') != -1) { + return 1; // we just need to know if this value is >0 + } } return 0; - }; +}; - QueryPlanDPSize.createJoinTree = function(leftPlan, rightPlan) { +QueryPlanDPSize.createJoinTree = function(leftPlan, rightPlan) { var varsLeft ="/"+leftPlan.vars.join("/")+"/"; var acumVars = leftPlan.vars.concat([]); var join = []; for(var i=0; iplan.cost) { - maxPlan = plan; + plans["_"+i+"_"] = {left: bgps[i], right:null, cost:bgps[i]._cost, i:('_'+i+'_'), vars:vars}; + var plan = {left: bgps[i], right:null, cost:bgps[i]._cost, i:('_'+i+'_'), vars:vars}; + bestPlans["_"+i+"_"] = plan; + delete bgps[i]['_cost']; + cache["_"+i+"_"] = true; + sizes['1'].push("_"+i+"_"); + if(maxPlan == null || maxPlan.cost>plan.cost) { + maxPlan = plan; + } } - } - - // dynamic programming -> build plans of increasing size - for(var s=2; s<=bgps.length; s++) { // size - for(var sl=1; sl build plans of increasing size + for(var s=2; s<=bgps.length; s++) { // size + for(var sl=1; sl currPlan.cost) { - if(maxSize === s) { - maxPlan = currPlan; - } - bestPlans[currPlan.i] = currPlan; + var costUnion = currPlan.cost+1; + if(bestPlans[currPlan.i] != null) { + costUnion = bestPlans[currPlan.i].cost; + } + + var acum = sizes[s] || []; + acum.push(currPlan.i); + plans[currPlan.i] = currPlan; + sizes[s] = acum; + + if(costUnion > currPlan.cost) { + if(maxSize === s) { + maxPlan = currPlan; + } + bestPlans[currPlan.i] = currPlan; + } + } + } + } } - } } - } } - } } - } - groupResults.push(maxPlan); + groupResults.push(maxPlan); } @@ -28029,132 +27464,132 @@ var acum = null; for(var g=0; g 0) { - for(var i=0; i oid) and an out cache (oid -> value) - * returns a bindings map (var -> value) storing in cache all the missing values for oids - * - * This is required just to save lookups when final results are generated. - */ - QueryEngine.QueryEngine.prototype.copyDenormalizedBindings = function(bindingsList, out, callback) { +}; + +/** + * Receives a bindings map (var -> oid) and an out cache (oid -> value) + * returns a bindings map (var -> value) storing in cache all the missing values for oids + * + * This is required just to save lookups when final results are generated. + */ +QueryEngine.QueryEngine.prototype.copyDenormalizedBindings = function(bindingsList, out, callback) { var denormList = []; for(var i=0; i0) { - callback(true, true); + aqt.projection = [{"token": "variable", "kind": "*"}]; + this.executeSelect(aqt, queryEnv, defaultDataset, namedDataset, function(success, result){ + if(success) { + if(success) { + if(result.length>0) { + callback(true, true); + } else { + callback(true, false); + } + } else { + callback(false, result); + } } else { - callback(true, false); + callback(false, result); } - } else { - callback(false, result); - } - } else { - callback(false, result); - } - }); + }); } else if(aqt.kind === 'construct') { - aqt.projection = [{"token": "variable", "kind": "*"}]; - that = this; - this.executeSelect(aqt, queryEnv, defaultDataset, namedDataset, function(success, result){ - if(success) { - if(success) { - var result = that.denormalizeBindingsList(result, queryEnv); - if(result != null) { - var graph = new RDFJSInterface.Graph(); - - // CONSTRUCT WHERE {} case - if(aqt.template == null) { - aqt.template = {triplesContext: aqt.pattern}; - } - var blankIdCounter = 1; - var toClear = []; - for(var i=0; i1 && set2.length>1) { - var vars = []; - var vars1 = {}; - for(var p in set1[0]) { - vars1[p] = true; - } - for(p in set2[0]) { - if(vars1[p] != true) { - vars.push(p); - } - } - acum = []; - duplicates = {}; - for(var i=0; i (set union) - if(duplicates[idx.join("")]==null) { - for(j=0; j ok"); - duplicates[idx.join("")] = true; - } + var vars = []; + var vars1 = {}; + for(var p in set1[0]) { + vars1[p] = true; + } + for(p in set2[0]) { + if(vars1[p] != true) { + vars.push(p); + } + } + acum = []; + duplicates = {}; + for(var i=0; i (set union) + if(duplicates[idx.join("")]==null) { + for(j=0; j ok"); + duplicates[idx.join("")] = true; + } - } - } + } + } - return acum; + return acum; } else { - return bindings; + return bindings; } - }; +}; - QueryEngine.QueryEngine.prototype.executeJOIN = function(projection, dataset, patterns, env) { +QueryEngine.QueryEngine.prototype.executeJOIN = function(projection, dataset, patterns, env) { var setQuery1 = patterns.lvalue; var setQuery2 = patterns.rvalue; var set1 = null; @@ -29528,70 +28963,70 @@ set1 = that.executeSelectUnit(projection, dataset, setQuery1, env); if(set1 == null) { - return null; + return null; } set2 = that.executeSelectUnit(projection, dataset, setQuery2, env); if(set2 == null) { - return null; + return null; } - - + + var result = null; if(set1.length ===0 || set2.length===0) { - result = []; + result = []; } else { - var commonVarsTmp = {}; - var commonVars = []; - - for(var p in set1[0]) - commonVarsTmp[p] = false; - for(var p in set2[0]) { - if(commonVarsTmp[p] === false) - commonVars.push(p); - } - - if(commonVars.length == 0) { - result = QueryPlan.joinBindings(set1,set2); - } else if(this.abstractQueryTree.treeWithUnion(setQuery1) || - this.abstractQueryTree.treeWithUnion(setQuery2)) { - result = QueryPlan.joinBindings(set1,set2); - } else { - result = QueryPlan.joinBindings2(commonVars, set1, set2); - } + var commonVarsTmp = {}; + var commonVars = []; + + for(var p in set1[0]) + commonVarsTmp[p] = false; + for(var p in set2[0]) { + if(commonVarsTmp[p] === false) + commonVars.push(p); + } + + if(commonVars.length == 0) { + result = QueryPlan.joinBindings(set1,set2); + } else if(this.abstractQueryTree.treeWithUnion(setQuery1) || + this.abstractQueryTree.treeWithUnion(setQuery2)) { + result = QueryPlan.joinBindings(set1,set2); + } else { + result = QueryPlan.joinBindings2(commonVars, set1, set2); + } } result = QueryFilters.checkFilters(patterns, result, false, dataset, env, that); return result; - }; +}; - QueryEngine.QueryEngine.prototype.rangeQuery = function(quad, queryEnv) { +QueryEngine.QueryEngine.prototype.rangeQuery = function(quad, queryEnv) { var that = this; //console.log("BEFORE:"); //console.log("QUAD:"); //console.log(quad); var key = that.normalizeQuad(quad, queryEnv, false); if(key != null) { - //console.log("RANGE QUERY:") - //console.log(key); - //console.log(new QuadIndexCommon.Pattern(key)); - var quads = that.backend.range(new QuadIndexCommon.Pattern(key)); - //console.log("retrieved"); - //console.log(quads) - if(quads == null || quads.length == 0) { - return []; - } else { - return quads; - } + //console.log("RANGE QUERY:") + //console.log(key); + //console.log(new QuadIndexCommon.Pattern(key)); + var quads = that.backend.range(new QuadIndexCommon.Pattern(key)); + //console.log("retrieved"); + //console.log(quads) + if(quads == null || quads.length == 0) { + return []; + } else { + return quads; + } } else { - console.log("ERROR normalizing quad"); - return null; + console.log("ERROR normalizing quad"); + return null; } - }; +}; // Update queries - QueryEngine.QueryEngine.prototype.executeUpdate = function(syntaxTree, callback) { +QueryEngine.QueryEngine.prototype.executeUpdate = function(syntaxTree, callback) { var prologue = syntaxTree.prologue; var units = syntaxTree.units; var that = this; @@ -29601,53 +29036,53 @@ this.registerNsInEnvironment(prologue, queryEnv); for(var i=0; i'; - } else if(quad.object.lang != null) { - quad.object.value = '"'+quad.object.value+'"@'+quad.object.lang; - } else { - quad.object.value = '"'+quad.object.value+'"'; - } - } - oid = this.lexicon.registerLiteral(quad.object.literal || quad.object.value); - if(quad.object.literal != null) { - quad.object = this.lexicon.parseLiteral(quad.object.literal); - delete quad.object['literal']; - } - object = oid; - } else { - maybeBlankOid = blanks[quad.object.blank || quad.object.value]; - if(maybeBlankOid == null) { - maybeBlankOid = this.lexicon.registerBlank(quad.object.blank || quad.object.value); - blanks[(quad.object.blank || quad.object.value)] = maybeBlankOid; - } - if(quad.object.token == null) { - quad.object.token = 'blank'; - quad.object.value = quad.object.blank; - delete quad.object['blank']; - } - - object = maybeBlankOid; - } - - // graph - if(quad.graph['uri'] || quad.graph.token === 'uri') { - oid = this.lexicon.registerUri(quad.graph.uri || quad.graph.value); - if(quad.graph.uri != null) { - quad.graph = {'token': 'uri', 'value': quad.graph.uri}; - delete quad.subject['uri']; - } - this.lexicon.registerGraph(oid); - graph = oid; - - } else if(quad.graph['literal'] || quad.graph.token === 'literal') { - oid = this.lexicon.registerLiteral(quad.graph.literal || quad.graph.value); - if(quad.predicate.literal != null) { - quad.predicate = this.lexicon.parseLiteral(quad.predicate.literal); - delete quad.predicate['literal']; - } - graph = oid; - } else { - maybeBlankOid = blanks[quad.graph.blank || quad.graph.value]; - if(maybeBlankOid == null) { - maybeBlankOid = this.lexicon.registerBlank(quad.graph.blank || quad.graph.value); - blanks[(quad.graph.blank || quad.graph.value)] = maybeBlankOid; - } - if(quad.graph.token == null) { - quad.graph.token = 'blank'; - quad.graph.value = quad.graph.blank; - delete quad.graph['blank']; + quad = quads[i]; + + // subject + if(quad.subject['uri'] || quad.subject.token === 'uri') { + oid = this.lexicon.registerUri(quad.subject.uri || quad.subject.value); + if(quad.subject.uri != null) { + quad.subject = {'token': 'uri', 'value': quad.subject.uri}; + delete quad.subject['uri']; + } + subject = oid; + } else if(quad.subject['literal'] || quad.subject.token === 'literal') { + oid = this.lexicon.registerLiteral(quad.subject.literal || quad.subject.value); + if(quad.subject.literal != null) { + quad.subject = this.lexicon.parseLiteral(quad.subject.literal); + delete quad.subject['literal']; + } + subject = oid; + } else { + maybeBlankOid = blanks[quad.subject.blank || quad.subject.value]; + if(maybeBlankOid == null) { + maybeBlankOid = this.lexicon.registerBlank(quad.subject.blank || quad.subject.value); + blanks[(quad.subject.blank || quad.subject.value)] = maybeBlankOid; + } + if(quad.subject.token == null) { + quad.subject.token = 'blank'; + quad.subject.value = quad.subject.blank; + delete quad.subject['blank']; + } + subject = maybeBlankOid; + } + + // predicate + if(quad.predicate['uri'] || quad.predicate.token === 'uri') { + oid = this.lexicon.registerUri(quad.predicate.uri || quad.predicate.value); + if(quad.predicate.uri != null) { + quad.predicate = {'token': 'uri', 'value': quad.predicate.uri}; + delete quad.subject['uri']; + } + predicate = oid; + } else if(quad.predicate['literal'] || quad.predicate.token === 'literal') { + oid = this.lexicon.registerLiteral(quad.predicate.literal || quad.predicate.value); + if(quad.predicate.literal != null) { + quad.predicate = this.lexicon.parseLiteral(quad.predicate.literal); + delete quad.predicate['literal']; + } + predicate = oid; + } else { + maybeBlankOid = blanks[quad.predicate.blank || quad.predicate.value]; + if(maybeBlankOid == null) { + maybeBlankOid = this.lexicon.registerBlank(quad.predicate.blank || quad.predicate.value); + blanks[(quad.predicate.blank || quad.predicate.value)] = maybeBlankOid; + } + if(quad.predicate.token == null) { + quad.predicate.token = 'blank'; + quad.predicate.value = quad.predicate.blank; + delete quad.predicate['blank']; + } + predicate = maybeBlankOid; + } + + // object + if(quad.object['uri'] || quad.object.token === 'uri') { + oid = this.lexicon.registerUri(quad.object.uri || quad.object.value); + if(quad.object.uri != null) { + quad.object = {'token': 'uri', 'value': quad.object.uri}; + delete quad.subject['uri']; + } + object = oid; + } else if(quad.object['literal'] || quad.object.token === 'literal') { + if(quad.object.token === 'literal') { + if(quad.object.type != null) { + quad.object.value = '"'+quad.object.value+'"^^<'+quad.object.type+'>'; + } else if(quad.object.lang != null) { + quad.object.value = '"'+quad.object.value+'"@'+quad.object.lang; + } else { + quad.object.value = '"'+quad.object.value+'"'; + } + } + oid = this.lexicon.registerLiteral(quad.object.literal || quad.object.value); + if(quad.object.literal != null) { + quad.object = this.lexicon.parseLiteral(quad.object.literal); + delete quad.object['literal']; + } + object = oid; + } else { + maybeBlankOid = blanks[quad.object.blank || quad.object.value]; + if(maybeBlankOid == null) { + maybeBlankOid = this.lexicon.registerBlank(quad.object.blank || quad.object.value); + blanks[(quad.object.blank || quad.object.value)] = maybeBlankOid; + } + if(quad.object.token == null) { + quad.object.token = 'blank'; + quad.object.value = quad.object.blank; + delete quad.object['blank']; + } + + object = maybeBlankOid; + } + + // graph + if(quad.graph['uri'] || quad.graph.token === 'uri') { + oid = this.lexicon.registerUri(quad.graph.uri || quad.graph.value); + if(quad.graph.uri != null) { + quad.graph = {'token': 'uri', 'value': quad.graph.uri}; + delete quad.subject['uri']; + } + this.lexicon.registerGraph(oid); + graph = oid; + + } else if(quad.graph['literal'] || quad.graph.token === 'literal') { + oid = this.lexicon.registerLiteral(quad.graph.literal || quad.graph.value); + if(quad.predicate.literal != null) { + quad.predicate = this.lexicon.parseLiteral(quad.predicate.literal); + delete quad.predicate['literal']; + } + graph = oid; + } else { + maybeBlankOid = blanks[quad.graph.blank || quad.graph.value]; + if(maybeBlankOid == null) { + maybeBlankOid = this.lexicon.registerBlank(quad.graph.blank || quad.graph.value); + blanks[(quad.graph.blank || quad.graph.value)] = maybeBlankOid; + } + if(quad.graph.token == null) { + quad.graph.token = 'blank'; + quad.graph.value = quad.graph.blank; + delete quad.graph['blank']; + } + graph = maybeBlankOid; } - graph = maybeBlankOid; - } - originalQuad = quad; - quad = {subject: subject, predicate:predicate, object:object, graph: graph}; - key = new QuadIndexCommon.NodeKey(quad); + originalQuad = quad; + quad = {subject: subject, predicate:predicate, object:object, graph: graph}; + key = new QuadIndexCommon.NodeKey(quad); - var result = this.backend.search(key); - if(!result) { - result = this.backend.index(key); - if(result == true){ - if(this.eventsOnBatchLoad) - this.callbacksBackend.nextGraphModification(Callbacks.added, [originalQuad,quad]); - counter = counter + 1; - } else { - success = false; - break; + var result = this.backend.search(key); + if(!result) { + result = this.backend.index(key); + if(result == true){ + if(this.eventsOnBatchLoad) + this.callbacksBackend.nextGraphModification(Callbacks.added, [originalQuad,quad]); + counter = counter + 1; + } else { + success = false; + break; + } } - } } if(this.lexicon.updateAfterWrite != null) - this.lexicon.updateAfterWrite(); + this.lexicon.updateAfterWrite(); var exitFn = function(){ - if(success) { - if(callback) - callback(true, counter); - } else { - if(callback) - callback(false, null); - } + if(success) { + if(callback) + callback(true, counter); + } else { + if(callback) + callback(false, null); + } }; if(this.eventsOnBatchLoad) { - this.callbacksBackend.endGraphModification(function(){ - exitFn(); - }); + this.callbacksBackend.endGraphModification(function(){ + exitFn(); + }); } else { - exitFn(); + exitFn(); } - + if(success) { - return counter; + return counter; } else { - return null; + return null; } - }; +}; // @modified dp - QueryEngine.QueryEngine.prototype.computeCosts = function (quads, env) { +QueryEngine.QueryEngine.prototype.computeCosts = function (quads, env) { for (var i = 0; i < quads.length; i++) { - quads[i]['_cost'] = this.quadCost(quads[i], env); + quads[i]['_cost'] = this.quadCost(quads[i], env); } return quads; - }; +}; // Low level operations for update queries - QueryEngine.QueryEngine.prototype._executeModifyQuery = function(aqt, queryEnv, callback) { +QueryEngine.QueryEngine.prototype._executeModifyQuery = function(aqt, queryEnv, callback) { var that = this; var querySuccess = true; var error = null; @@ -29863,271 +29298,271 @@ aqt['delete'] = aqt['delete'] == null ? [] : aqt['delete']; Utils.seq( - function(k) { - // select query + function(k) { + // select query - var defaultGraph = []; - var namedGraph = []; + var defaultGraph = []; + var namedGraph = []; - if(aqt['with'] != null) { - defaultGraph.push(aqt['with']); - } + if(aqt['with'] != null) { + defaultGraph.push(aqt['with']); + } - if(aqt['using'] != null) { - namedGraph = []; - for(var i=0; i { ?s ?p ?o } } WHERE { GRAPH <"+graph+"> { ?s ?p ?o } }", function(success, results){ - foundErrorDeleting = !success; - k(floop, env); + var that = this; + var graphs = this.lexicon.registeredGraphs(true); + if(graphs!=null) { + var foundErrorDeleting = false; + Utils.repeat(0, graphs.length,function(k,env) { + var graph = graphs[env._i]; + var floop = arguments.callee; + if(!foundErrorDeleting) { + that.execute("DELETE { GRAPH <"+graph+"> { ?s ?p ?o } } WHERE { GRAPH <"+graph+"> { ?s ?p ?o } }", function(success, results){ + foundErrorDeleting = !success; + k(floop, env); + }); + } else { + k(floop, env); + } + }, function(env) { + callback(!foundErrorDeleting); }); - } else { - k(floop, env); - } - }, function(env) { - callback(!foundErrorDeleting); - }); - } else { - callback(false, "Error deleting named graphs"); - } - } else if(destinyGraph === 'all') { - var that = this; - this.execute("CLEAR DEFAULT", function(success, result) { - if(success) { - that.execute("CLEAR NAMED", callback); } else { - callback(false,result); + callback(false, "Error deleting named graphs"); } - }); + } else if(destinyGraph === 'all') { + var that = this; + this.execute("CLEAR DEFAULT", function(success, result) { + if(success) { + that.execute("CLEAR NAMED", callback); + } else { + callback(false,result); + } + }); } else { - // destinyGraph is an URI - if(destinyGraph.token == 'uri') { - var graphUri = Utils.lexicalFormBaseUri(destinyGraph,queryEnv); - if(graphUri != null) { - this.execute("DELETE { GRAPH <"+graphUri+"> { ?s ?p ?o } } WHERE { GRAPH <"+graphUri+"> { ?s ?p ?o } }", callback); + // destinyGraph is an URI + if(destinyGraph.token == 'uri') { + var graphUri = Utils.lexicalFormBaseUri(destinyGraph,queryEnv); + if(graphUri != null) { + this.execute("DELETE { GRAPH <"+graphUri+"> { ?s ?p ?o } } WHERE { GRAPH <"+graphUri+"> { ?s ?p ?o } }", callback); + } else { + callback(false, "wrong graph URI"); + } } else { - callback(false, "wrong graph URI"); + callback(false, "wrong graph URI"); } - } else { - callback(false, "wrong graph URI"); - } } - }; +}; - QueryEngine.QueryEngine.prototype.checkGroupSemantics = function(groupVars, projectionVars) { +QueryEngine.QueryEngine.prototype.checkGroupSemantics = function(groupVars, projectionVars) { if(groupVars === 'singleGroup') { - return true; + return true; } var projection = {}; for(var i=0; i ?p ?o } WHERE { GRAPH <" + graphUri + "> { <" + uri + "> ?p ?o } }"; var that = this; @@ -30413,64 +29848,64 @@ this.engine.registerNsInEnvironment(null, queryEnv); var bindings = []; this.engine.execute(query, function(success, graph){ - if(success) { - var node = graph; - var mustFlush = false; - var observer = function(event, triples){ - if(event === 'eventsFlushed' && mustFlush ) { - mustFlush = false; - try { - callback(node); - }catch(e){} - } else if(event !== 'eventsFlushed') { - mustFlush = true; - for(var i = 0; i - *
- * The first argument to this function is the URL/FS location - * of the store script. - *
- *
- * This parameter is mandatory in the browser. It is safe to - * ignore this parameter in Node.js. - *
- *
- * If support for web workers is not present, a regular - * store object will be initialized and returned. - *
- *
- * - * @param {String} [scriptPath] URL of the RDFStore script - * @param {Object[]} [args] Arguments to be passed to the store that will be created - * @param {Function} callback Callback function that will be invoked with an error flag and the connection/store object. - */ - Store.connect = function() { +var MongodbQueryEngine = { MongodbQueryEngine: function(){ throw 'MongoDB backend not supported in the browser version' } }; +var RDFStoreClient = RDFStoreClient; +/** + * Version of the store + */ +Store.VERSION = "0.8.1"; + +/** + * Create a new RDFStore instance that will be + * executed in a web worker in the browser or a new process + * in Node.js. + *
+ *
+ * The first argument to this function is the URL/FS location + * of the store script. + *
+ *
+ * This parameter is mandatory in the browser. It is safe to + * ignore this parameter in Node.js. + *
+ *
+ * If support for web workers is not present, a regular + * store object will be initialized and returned. + *
+ *
+ * + * @param {String} [scriptPath] URL of the RDFStore script + * @param {Object[]} [args] Arguments to be passed to the store that will be created + * @param {Function} callback Callback function that will be invoked with an error flag and the connection/store object. + */ +Store.connect = function() { var path, args, callback; if(arguments.length == 1) { - path = __dirname; - args = {}; - callback = arguments[0]; - } else if(arguments.length == 2) { - if(typeof(arguments[0]) === 'string') { - path = arguments[0]; + path = __dirname; args = {}; - } else { - path = __dirname+"/index.js"; - args = arguments[0]; - } - callback = arguments[1]; + callback = arguments[0]; + } else if(arguments.length == 2) { + if(typeof(arguments[0]) === 'string') { + path = arguments[0]; + args = {}; + } else { + path = __dirname+"/index.js"; + args = arguments[0]; + } + callback = arguments[1]; } else { - path = arguments[0]; - args = arguments[1]; - callback = arguments[2]; + path = arguments[0]; + args = arguments[1]; + callback = arguments[2]; } try { - if(!!Worker) { - new RDFStoreClient.RDFStoreClient(path, args, function(success,connection) { - callback(success, connection); - }); - } else { - Store.create(args,function(connection){ - callback(false, connection); - }); - } + if(!!Worker) { + new RDFStoreClient.RDFStoreClient(path, args, function(success,connection) { + callback(success, connection); + }); + } else { + Store.create(args,function(connection){ + callback(false, connection); + }); + } } catch(e) { - Store.create(args,function(connection){ - callback(false, connection); - }); - } - }; - - /** - * Creates a new instance of the store. - * - * The function accepts two optional arguments. - *
- * If only one argument is passed it must be a - * callback function that will be invoked when the - * store had been created.
- *
- * If two arguments are passed the first one must - * be a map of configuration parameters for the - * store, and the second one the callback function.
- *
- * Take a look at the Store constructor function for - * a detailed list of possible configuration parameters.
- * - * @param {Object[]} [args] Arguments to be passed to the store that will be created - * @param {Function} [callback] Callback function that will be invoked with an error flag and the connection/store object. - */ - Store.create = function(){ + Store.create(args,function(connection){ + callback(false, connection); + }); + } +}; + +/** + * Creates a new instance of the store. + * + * The function accepts two optional arguments. + *
+ * If only one argument is passed it must be a + * callback function that will be invoked when the + * store had been created.
+ *
+ * If two arguments are passed the first one must + * be a map of configuration parameters for the + * store, and the second one the callback function.
+ *
+ * Take a look at the Store constructor function for + * a detailed list of possible configuration parameters.
+ * + * @param {Object[]} [args] Arguments to be passed to the store that will be created + * @param {Function} [callback] Callback function that will be invoked with an error flag and the connection/store object. + */ +Store.create = function(){ if(arguments.length == 1) { - return new Store.Store(arguments[0]); + return new Store.Store(arguments[0]); } else if(arguments.length == 2) { - return new Store.Store(arguments[0], arguments[1]); + return new Store.Store(arguments[0], arguments[1]); } else { - return new Store.Store(); + return new Store.Store(); }; - }; - - /** - * Creates a new store.
- *
- * It accepts two optional arguments, a map of configuration - * options for the store and a callback function.
- * - * @constructor - * @param {Function} [callback] Callback that will be invoked when the store has been created - * @param {Object} [params] - *
    - *
  • persistent: should the store use persistence?
  • - *
  • treeOrder: in versions of the store backed by the native indexing system, the order of the BTree indices
  • - *
  • name: when using persistence, the name for this store. In the MongoDB backed version, name of the DB used by the store. By default 'rdfstore_js' is used
  • - *
  • overwrite: clears the persistent storage
  • - *
  • maxCacheSize: if using persistence, maximum size of the index cache
  • - *
  • engine: the persistent storage to use, a value mongodb selects the MongoDB engine
  • - *
  • mongoDomain: when engine=mongodb, server domain name or IP address where the MongoDB server backing the store is running. By default '127.0.0.1' is used
  • - *
  • mongoPort: when engine=mongodb, port where the MongoDB server is running. By default 27017 is used
  • - *
  • mongoOptions: when engine=mongodb, additional options for the MongoDB driver. By default {} is used
  • - *
- */ - Store.Store = function(arg1, arg2) { +}; + +/** + * Creates a new store.
+ *
+ * It accepts two optional arguments, a map of configuration + * options for the store and a callback function.
+ * + * @constructor + * @param {Function} [callback] Callback that will be invoked when the store has been created + * @param {Object} [params] + *
    + *
  • persistent: should the store use persistence?
  • + *
  • treeOrder: in versions of the store backed by the native indexing system, the order of the BTree indices
  • + *
  • name: when using persistence, the name for this store. In the MongoDB backed version, name of the DB used by the store. By default 'rdfstore_js' is used
  • + *
  • overwrite: clears the persistent storage
  • + *
  • maxCacheSize: if using persistence, maximum size of the index cache
  • + *
  • engine: the persistent storage to use, a value mongodb selects the MongoDB engine
  • + *
  • mongoDomain: when engine=mongodb, server domain name or IP address where the MongoDB server backing the store is running. By default '127.0.0.1' is used
  • + *
  • mongoPort: when engine=mongodb, port where the MongoDB server is running. By default 27017 is used
  • + *
  • mongoOptions: when engine=mongodb, additional options for the MongoDB driver. By default {} is used
  • + *
+ */ +Store.Store = function(arg1, arg2) { var callback = null; var params = null; if(arguments.length == 0) { - params ={}; + params ={}; } else if(arguments.length == 1) { - params = {}; - callback = arg1; + params = {}; + callback = arg1; } else if(arguments.length > 1) { - params = arg1; - callback = arg2; + params = arg1; + callback = arg2; } else { - throw("An optional argument map and a callback must be provided"); - } - - if(params['treeOrder'] == null) { - params['treeOrder'] = 15; + throw("An optional argument map and a callback must be provided"); } - this.functionMap = {}; - - var that = this; - this.customFns = {}; - if(params['engine']==='mongodb') { - this.isMongodb = true; - this.engine = new MongodbQueryEngine.MongodbQueryEngine(params); - this.engine.readConfiguration(function(){ - if(params['overwrite'] === true) { - that.engine.clean(function(){ - callback(that); - }); - } else { - callback(that); - } - }); - } else { - new Lexicon.Lexicon(function(lexicon){ - if(params['overwrite'] === true) { - // delete lexicon values - lexicon.clear(); - } - new QuadBackend.QuadBackend(params, function(backend){ - if(params['overwrite'] === true) { - // delete index values - backend.clear(); - } - params.backend = backend; - params.lexicon =lexicon; - that.engine = new QueryEngine.QueryEngine(params); - if(callback) { - callback(that); - } - }); - },params['name']); + if(params['treeOrder'] == null) { + params['treeOrder'] = 15; } - }; + this.functionMap = {}; - /** - * An instance of RDF JS Interface RDFEnvironment - * associated to this graph instance. - */ - Store.Store.prototype.rdf = RDFJSInterface.rdf; - Store.Store.prototype.rdf.api = RDFJSInterface; - - /** - * Registers a new function with an associated name that can - * be invoked as 'custom:fn_name(arg1,arg2,...,argn)' inside - * a SPARQL query. - *
- * The registered function will receive two arguments, an - * instance of the store's query filters engine and a list - * with the arguments received by the function in the SPARQL query. - *
- * The function must return a single token value that can - * consist in a literal value or an URI. - *
- * The following is an example literal value: - * {token: 'literal', type:"http://www.w3.org/2001/XMLSchema#integer", value:'3'} - * This is an example URI value: - * {token: 'uri', value:'http://test.com/my_uri'} - *
- * The query filters engine can be used to perform common operations - * on the input values. - * An error can be returne dusing the 'ebvError' function of the engine. - * True and false values can be built directly using the 'ebvTrue' and - * 'ebvFalse' functions. - * - * A complete reference of the available functions can be found in the - * documentation or source code of the QueryFilters module. - * - * @arguments: - * @param {String} [name]: name of the custom function, it will be accesible as custom:name in the query - * @param {Function} [function]: lambda function with the code for the query custom function. - */ - Store.Store.prototype.registerCustomFunction = function(name, fn) { + var that = this; + this.customFns = {}; + if(params['engine']==='mongodb') { + this.isMongodb = true; + this.engine = new MongodbQueryEngine.MongodbQueryEngine(params); + this.engine.readConfiguration(function(){ + if(params['overwrite'] === true) { + that.engine.clean(function(){ + callback(that); + }); + } else { + callback(that); + } + }); + } else { + new Lexicon.Lexicon(function(lexicon){ + if(params['overwrite'] === true) { + // delete lexicon values + lexicon.clear(); + } + new QuadBackend.QuadBackend(params, function(backend){ + if(params['overwrite'] === true) { + // delete index values + backend.clear(); + } + params.backend = backend; + params.lexicon =lexicon; + that.engine = new QueryEngine.QueryEngine(params); + if(callback) { + callback(that); + } + }); + },params['name']); + } +}; + + +/** + * An instance of RDF JS Interface RDFEnvironment + * associated to this graph instance. + */ +Store.Store.prototype.rdf = RDFJSInterface.rdf; +Store.Store.prototype.rdf.api = RDFJSInterface; + +/** + * Registers a new function with an associated name that can + * be invoked as 'custom:fn_name(arg1,arg2,...,argn)' inside + * a SPARQL query. + *
+ * The registered function will receive two arguments, an + * instance of the store's query filters engine and a list + * with the arguments received by the function in the SPARQL query. + *
+ * The function must return a single token value that can + * consist in a literal value or an URI. + *
+ * The following is an example literal value: + * {token: 'literal', type:"http://www.w3.org/2001/XMLSchema#integer", value:'3'} + * This is an example URI value: + * {token: 'uri', value:'http://test.com/my_uri'} + *
+ * The query filters engine can be used to perform common operations + * on the input values. + * An error can be returne dusing the 'ebvError' function of the engine. + * True and false values can be built directly using the 'ebvTrue' and + * 'ebvFalse' functions. + * + * A complete reference of the available functions can be found in the + * documentation or source code of the QueryFilters module. + * + * @arguments: + * @param {String} [name]: name of the custom function, it will be accesible as custom:name in the query + * @param {Function} [function]: lambda function with the code for the query custom function. + */ +Store.Store.prototype.registerCustomFunction = function(name, fn) { this.customFns[name] = fn; this.engine.setCustomFunctions(this.customFns); - }; - - /** - * Executes a query in the store.
- *
- * There are two possible ways of invoking this function, - * providing a pair of arrays of namespaces that will be - * used to compute the union of the default and named - * dataset, or without them. - *
- *
- * Both invocations receive as an optional last parameter - * a callback function that will receive the return status - * of the query and the results. - *
- *
- * Results can have different formats: - *
    - *
  • SELECT queries: array of binding maps
  • - *
  • CONSTRUCT queries: RDF JS Interface Graph object
  • - *
  • ASK queries: JS boolean value
  • - *
  • LOAD/INSERT... queries: Number of triples modified/inserted
  • - *
- * - * @arguments: - * @param {String} query - * @param {String} [defaultURIs] default namespaces - * @param {String} [namespacesURIs] named namespaces - * @param {Function} [callback] - */ - Store.Store.prototype.execute = function() { +}; + +/** + * Executes a query in the store.
+ *
+ * There are two possible ways of invoking this function, + * providing a pair of arrays of namespaces that will be + * used to compute the union of the default and named + * dataset, or without them. + *
+ *
+ * Both invocations receive as an optional last parameter + * a callback function that will receive the return status + * of the query and the results. + *
+ *
+ * Results can have different formats: + *
    + *
  • SELECT queries: array of binding maps
  • + *
  • CONSTRUCT queries: RDF JS Interface Graph object
  • + *
  • ASK queries: JS boolean value
  • + *
  • LOAD/INSERT... queries: Number of triples modified/inserted
  • + *
+ * + * @arguments: + * @param {String} query + * @param {String} [defaultURIs] default namespaces + * @param {String} [namespacesURIs] named namespaces + * @param {Function} [callback] + */ +Store.Store.prototype.execute = function() { if(arguments.length === 3) { - this.executeWithEnvironment(arguments[0], - arguments[1], - arguments[2]); + this.executeWithEnvironment(arguments[0], + arguments[1], + arguments[2]); } else if(arguments.length === 4) { - this.executeWithEnvironment(arguments[0], - arguments[1], - arguments[2], - arguments[3]); + this.executeWithEnvironment(arguments[0], + arguments[1], + arguments[2], + arguments[3]); } else { - var queryString; - var callback; - - if(arguments.length === 1) { - queryString = arguments[0]; - var callback = function(){}; - } else if(arguments.length === 2) { - queryString = arguments[0]; - callback = arguments [1]; - } - this.engine.execute(queryString, callback); - } - }; - - /** - * A variation of the execute function that expects - * arguments containing values for the default and named - * graphs that will be used in the query. - * - * - * @arguments: - * @param {String} query - * @param {String} URIs default namespaces - * @param {String} URIs named namespaces - * @param {Function} [callback] - */ - Store.Store.prototype.executeWithEnvironment = function() { + var queryString; + var callback; + + if(arguments.length === 1) { + queryString = arguments[0]; + var callback = function(){}; + } else if(arguments.length === 2) { + queryString = arguments[0]; + callback = arguments [1]; + } + this.engine.execute(queryString, callback); + } +}; + +/** + * A variation of the execute function that expects + * arguments containing values for the default and named + * graphs that will be used in the query. + * + * + * @arguments: + * @param {String} query + * @param {String} URIs default namespaces + * @param {String} URIs named namespaces + * @param {Function} [callback] + */ +Store.Store.prototype.executeWithEnvironment = function() { var queryString, defaultGraphs, namedGraphs; if(arguments.length === 3) { - queryString = arguments[0]; - // JSDoc fails if this is pushed outside - var callback = function(){}; - defaultGraphs = arguments[1]; - namedGraphs = arguments[2]; + queryString = arguments[0]; + // JSDoc fails if this is pushed outside + var callback = function(){}; + defaultGraphs = arguments[1]; + namedGraphs = arguments[2]; } else if(arguments.length === 4) { - queryString = arguments[0]; - var callback = arguments [3]; - defaultGraphs = arguments[1]; - namedGraphs = arguments[2]; + queryString = arguments[0]; + var callback = arguments [3]; + defaultGraphs = arguments[1]; + namedGraphs = arguments[2]; } var defaultGraphsNorm = []; var namedGraphsNorm = []; for(var i=0; i - *
- * The function accepts as mandatory parameter a callback - * function that will receive the a success notification and the returned graph.
- *
- * Optionally, the URI of the graph can also be passed as - * the first argument. If no graph is specified, the - * default graph will be returned.
- * - * @arguments - * @param {String} [graphURI] If this parameter is missing, the default graph will be returned - * @param {Functon} callback - */ - Store.Store.prototype.graph = function() { +}; + +/** + * Retrieves all the quads belonging to a certain graph + * in the store as a RDF JS Interface Graph object.
+ *
+ * The function accepts as mandatory parameter a callback + * function that will receive the a success notification and the returned graph.
+ *
+ * Optionally, the URI of the graph can also be passed as + * the first argument. If no graph is specified, the + * default graph will be returned.
+ * + * @arguments + * @param {String} [graphURI] If this parameter is missing, the default graph will be returned + * @param {Functon} callback + */ +Store.Store.prototype.graph = function() { var graphUri = null; var callback = null; if(arguments.length === 1) { - callback = arguments[0] || function(){}; - graphUri = this.engine.lexicon.defaultGraphUri; + callback = arguments[0] || function(){}; + graphUri = this.engine.lexicon.defaultGraphUri; } else if(arguments.length === 2) { - callback = arguments[1] || function(){}; - graphUri = arguments[0]; + callback = arguments[1] || function(){}; + graphUri = arguments[0]; } else { - throw("An optional graph URI and a callback function must be provided"); + throw("An optional graph URI and a callback function must be provided"); } if(this.rdf.resolve(graphUri) != null) { - graphUri = this.rdf.resolve(graphUri); + graphUri = this.rdf.resolve(graphUri); } this.engine.execute("CONSTRUCT { ?s ?p ?o } WHERE { GRAPH <" + graphUri + "> { ?s ?p ?o } }", callback); - }; - - /** - * Retrieves all the quads belonging to a certain node - * in the store as a RDF JS Interface Graph object containing - * the collection of triples whose subject is the provided - * node URI.
- *
- * The function accepts as mandatory parameters the node URI and - * a callback unction that will receive a success notification and the returned node.
- *
- * Optionally, the URI of the graph where the node is contained - * can also be passed as the first argument.
- *
- * If no graph is specified, the node will be looked into the - * default graph.
- * - * @arguments - * @param {String} nodeURI URI of the node to look for - * @param {String} [graphURI] If this parameter is missing, the node will be looked into the default graph - * @param {Functon} callback - */ - Store.Store.prototype.node = function() { +}; + +/** + * Retrieves all the quads belonging to a certain node + * in the store as a RDF JS Interface Graph object containing + * the collection of triples whose subject is the provided + * node URI.
+ *
+ * The function accepts as mandatory parameters the node URI and + * a callback unction that will receive a success notification and the returned node.
+ *
+ * Optionally, the URI of the graph where the node is contained + * can also be passed as the first argument.
+ *
+ * If no graph is specified, the node will be looked into the + * default graph.
+ * + * @arguments + * @param {String} nodeURI URI of the node to look for + * @param {String} [graphURI] If this parameter is missing, the node will be looked into the default graph + * @param {Functon} callback + */ +Store.Store.prototype.node = function() { var graphUri = null; var callback = null; var nodeUri = null; if(arguments.length === 2) { - nodeUri = arguments[0]; - callback = arguments[1] || function(){}; - graphUri = this.engine.lexicon.defaultGraphUri; + nodeUri = arguments[0]; + callback = arguments[1] || function(){}; + graphUri = this.engine.lexicon.defaultGraphUri; } else if(arguments.length === 3) { - nodeUri = arguments[0]; - graphUri = arguments[1]; - callback = arguments[2] || function(){}; + nodeUri = arguments[0]; + graphUri = arguments[1]; + callback = arguments[2] || function(){}; } else { - throw("An optional graph URI, node URI and a callback function must be provided"); + throw("An optional graph URI, node URI and a callback function must be provided"); } if(this.rdf.resolve(graphUri) != null) { - graphUri = this.rdf.resolve(graphUri); + graphUri = this.rdf.resolve(graphUri); } if(this.rdf.resolve(nodeUri) != null) { - nodeUri = this.rdf.resolve(nodeUri); + nodeUri = this.rdf.resolve(nodeUri); } this.engine.execute("CONSTRUCT { <" + nodeUri + "> ?p ?o } WHERE { GRAPH <" + graphUri + "> { <" + nodeUri + "> ?p ?o } }", callback); - }; - - /** - * Associates an event listener function to a node URI. Every time the collection - * of triples whose subject is the specified node URI changes, because an - * insertion or deletion, the provided callback function will be invoked - * receiving as a parameter a RDF JS Interface Graph object with the new - * collection of triples.
- *
- * The function accepts two mandatory arguments, the URI of the node to observe - * and the function that will receive the event notifications. An optional - * third parameter, consisting of a callback function, can be passed and will be invoked - * once the store had correctly configured the event listener.
- *
- * LOAD queries, batch loading data into the store, do not - * trigger events by default. If you wish to be notified - * by changes triggered by this kind of queries, invoke - * the *setBatchLoadEvents* function with a true argument.
- *
- * The event listener function can be removed using the stopObservingNode function. - * - * @arguments - * @param {String} nodeURI URI of the node to observe - * @param {Function} eventListener Function that will be notified with the events - * @param {Function} [callback] Function that will be invoked, once the event listener had been correctly set up. - */ - Store.Store.prototype.startObservingNode = function() { +}; + +/** + * Associates an event listener function to a node URI. Every time the collection + * of triples whose subject is the specified node URI changes, because an + * insertion or deletion, the provided callback function will be invoked + * receiving as a parameter a RDF JS Interface Graph object with the new + * collection of triples.
+ *
+ * The function accepts two mandatory arguments, the URI of the node to observe + * and the function that will receive the event notifications. An optional + * third parameter, consisting of a callback function, can be passed and will be invoked + * once the store had correctly configured the event listener.
+ *
+ * LOAD queries, batch loading data into the store, do not + * trigger events by default. If you wish to be notified + * by changes triggered by this kind of queries, invoke + * the *setBatchLoadEvents* function with a true argument.
+ *
+ * The event listener function can be removed using the stopObservingNode function. + * + * @arguments + * @param {String} nodeURI URI of the node to observe + * @param {Function} eventListener Function that will be notified with the events + * @param {Function} [callback] Function that will be invoked, once the event listener had been correctly set up. + */ +Store.Store.prototype.startObservingNode = function() { var uri, graphUri, callback; if(arguments.length === 2) { - uri = arguments[0]; - callback = arguments[1]; - this.engine.callbacksBackend.observeNode(uri, callback, function(){}); + uri = arguments[0]; + callback = arguments[1]; + this.engine.callbacksBackend.observeNode(uri, callback, function(){}); } else if(arguments.length === 3) { - uri = arguments[0]; - graphUri = arguments[1]; - callback = arguments[2]; - this.engine.callbacksBackend.observeNode(uri, graphUri, callback, function(){}); - } - }; - - /** - * Removes a callback function associated to a node.
- * The event listener function object must be passed as an argument.
- * - * @arguments - * @param {Function} eventListener The event listener function to remove, the same passed as an argument to startObservingNode - */ - Store.Store.prototype.stopObservingNode = function(callback) { + uri = arguments[0]; + graphUri = arguments[1]; + callback = arguments[2]; + this.engine.callbacksBackend.observeNode(uri, graphUri, callback, function(){}); + } +}; + +/** + * Removes a callback function associated to a node.
+ * The event listener function object must be passed as an argument.
+ * + * @arguments + * @param {Function} eventListener The event listener function to remove, the same passed as an argument to startObservingNode + */ +Store.Store.prototype.stopObservingNode = function(callback) { this.engine.callbacksBackend.stopObservingNode(callback); - }; - - /** - * Associates an event listener function to a SPARQL SELECT or - * CONSTRUCT query.
- * Every time an update (insert, delete...) query modified the - * triples in the store in a way that modifies the output of the - * query, the event listener will be invoked with an updated - * result.
- *
- * LOAD queries, batch loading data into the store, do not - * trigger events by default. If you wish to be notified - * by changes triggered by this kind of queries, invoke - * the setBatchLoadEvents function with a true argument.
- *
- * The event listener function can be removed invoking the - * stopObservingQuery function. - * - * @arguments - * @param {String} query SELECT or CONSTRUCT SPARQL query - * @param {Function} eventListener the function that will receive the notifications - * @param {Function} [callback] optional function that will be invoked when the stored had set up the event listener function. - */ - Store.Store.prototype.startObservingQuery = function() { +}; + +/** + * Associates an event listener function to a SPARQL SELECT or + * CONSTRUCT query.
+ * Every time an update (insert, delete...) query modified the + * triples in the store in a way that modifies the output of the + * query, the event listener will be invoked with an updated + * result.
+ *
+ * LOAD queries, batch loading data into the store, do not + * trigger events by default. If you wish to be notified + * by changes triggered by this kind of queries, invoke + * the setBatchLoadEvents function with a true argument.
+ *
+ * The event listener function can be removed invoking the + * stopObservingQuery function. + * + * @arguments + * @param {String} query SELECT or CONSTRUCT SPARQL query + * @param {Function} eventListener the function that will receive the notifications + * @param {Function} [callback] optional function that will be invoked when the stored had set up the event listener function. + */ +Store.Store.prototype.startObservingQuery = function() { var query = arguments[0]; var callback = arguments[1]; var endCallback = arguments[2]; if(endCallback!=null) { - this.engine.callbacksBackend.observeQuery(query, callback, endCallback); + this.engine.callbacksBackend.observeQuery(query, callback, endCallback); } else { - this.engine.callbacksBackend.observeQuery(query, callback, function(){}); - } - }; - - /** - * Removes a callback function associated to a SPARQL query.
- * The event listener function object must be passed as an argument. - * - * @arguments - * @param {Function} eventListener The event listener function to remove, the same passed as an argument to startObservingQuery - */ - Store.Store.prototype.stopObservingQuery = function(query) { + this.engine.callbacksBackend.observeQuery(query, callback, function(){}); + } +}; + +/** + * Removes a callback function associated to a SPARQL query.
+ * The event listener function object must be passed as an argument. + * + * @arguments + * @param {Function} eventListener The event listener function to remove, the same passed as an argument to startObservingQuery + */ +Store.Store.prototype.stopObservingQuery = function(query) { this.engine.callbacksBackend.stopObservingQuery(query); - }; - - /** - * Associates an event listener to a pattern expressed as the - * subject, predicate, object and graph string parameters passed - * to the function. To match any value in that position, a null - * value can be passed as an argument. e.g. subscribe(null, null, null, g, cb), - * will be notified with any change in the g graph.
- * The graph component of the pattern does not support a null value.
- *
- * Results will be notified as an Array of RDF JS Interface - * Triple objects.
- *
- * LOAD queries, batch loading data into the store, do not - * trigger events by default. If you wish to be notified - * by changes triggered by this kind of queries, invoke - * the setBatchLoadEvents function with a true argument. - * - * @arguments - * @param {String} s subject or null for any subject - * @param {String} p predicate or null for any predicate - * @param {String} o object or null for any object - * @param {String} g graph or null for any graph - * @param {Function} event listener function that will be notified when a change occurs - */ - Store.Store.prototype.subscribe = function(s, p, o, g, callback) { +}; + +/** + * Associates an event listener to a pattern expressed as the + * subject, predicate, object and graph string parameters passed + * to the function. To match any value in that position, a null + * value can be passed as an argument. e.g. subscribe(null, null, null, g, cb), + * will be notified with any change in the g graph.
+ * The graph component of the pattern does not support a null value.
+ *
+ * Results will be notified as an Array of RDF JS Interface + * Triple objects.
+ *
+ * LOAD queries, batch loading data into the store, do not + * trigger events by default. If you wish to be notified + * by changes triggered by this kind of queries, invoke + * the setBatchLoadEvents function with a true argument. + * + * @arguments + * @param {String} s subject or null for any subject + * @param {String} p predicate or null for any predicate + * @param {String} o object or null for any object + * @param {String} g graph or null for any graph + * @param {Function} event listener function that will be notified when a change occurs + */ +Store.Store.prototype.subscribe = function(s, p, o, g, callback) { var that = this; var adapterCb = function(event,triples){ - var acum = []; - var queryEnv = {blanks:{}, outCache:{}}; - var bindings = []; + var acum = []; + var queryEnv = {blanks:{}, outCache:{}}; + var bindings = []; - for(var i=0; isubscribe must be - * passed as an argument. - * - * @arguments - * @param {Function} callback The event listener to be removed - */ - Store.Store.prototype.unsubscribe = function(callback) { +}; + +/** + * Removes an event listener associated to a certain pattern. + * The function passed as an argument to subscribe must be + * passed as an argument. + * + * @arguments + * @param {Function} callback The event listener to be removed + */ +Store.Store.prototype.unsubscribe = function(callback) { var adapterCb = this.functionMap[callback]; this.engine.callbacksBackend.unsubscribe(adapterCb); delete this.functionMap[callback]; - }; - - /** - * Register a combination of prefix and URI fragment in the default instance - * of the RDF JS Interface API RDFEnvironment object associated - * to the store and available through the storeInstance.rdf property. - * - * @arguments - * @param {String} prefix The prefix to be associated - * @param {String} URIFragment URI fragment the provided prefix will be resolved - */ - Store.Store.prototype.setPrefix = function(prefix, uri) { +}; + +/** + * Register a combination of prefix and URI fragment in the default instance + * of the RDF JS Interface API RDFEnvironment object associated + * to the store and available through the storeInstance.rdf property. + * + * @arguments + * @param {String} prefix The prefix to be associated + * @param {String} URIFragment URI fragment the provided prefix will be resolved + */ +Store.Store.prototype.setPrefix = function(prefix, uri) { this.rdf.setPrefix(prefix, uri); - }; - - /** - * Defines the URI that will be used by default by the RDF JS Interface - * API RDFEnvironment object associated to the store and available - * through the storeInstance.rdf property. - * - * @arguments - * @param {String} URIFragment The URI fragment will be used by default - */ - Store.Store.prototype.setDefaultPrefix = function(uri) { +}; + +/** + * Defines the URI that will be used by default by the RDF JS Interface + * API RDFEnvironment object associated to the store and available + * through the storeInstance.rdf property. + * + * @arguments + * @param {String} URIFragment The URI fragment will be used by default + */ +Store.Store.prototype.setDefaultPrefix = function(uri) { this.rdf.setDefaultPrefix(uri); - }; - - /** - * Inserts a RDF JS Interface API Graph object into the store. - * The function receives a mandatory Graph object whose triples - * will be inserted. Optionally, a URI string for a graph and a - * callback function can be passed as arguments.
- *
- * If no graph URI is specified, triples will be inserted into the - * default graph.
- *
- * If the callback function is specified, it will be invoked when all the - * triples had been inserted into the store.
- * - * @arguments - * @param {RDFJSInterface.Graph} triples a RDF JS Interface Graph object - * @param {String} [graphURI] URI of the graph where the triples will be inserted. If it is missing, triples will be inserted in the default graph - * @param {String} [callback] A callback function that will be invoked with a success notification and the number of triples inserted - */ - Store.Store.prototype.insert = function() { +}; + +/** + * Inserts a RDF JS Interface API Graph object into the store. + * The function receives a mandatory Graph object whose triples + * will be inserted. Optionally, a URI string for a graph and a + * callback function can be passed as arguments.
+ *
+ * If no graph URI is specified, triples will be inserted into the + * default graph.
+ *
+ * If the callback function is specified, it will be invoked when all the + * triples had been inserted into the store.
+ * + * @arguments + * @param {RDFJSInterface.Graph} triples a RDF JS Interface Graph object + * @param {String} [graphURI] URI of the graph where the triples will be inserted. If it is missing, triples will be inserted in the default graph + * @param {String} [callback] A callback function that will be invoked with a success notification and the number of triples inserted + */ +Store.Store.prototype.insert = function() { var graph; var triples; var callback; if(arguments.length === 1) { - triples = arguments[0]; + triples = arguments[0]; } else if(arguments.length === 2) { - graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri); - triples = arguments[0]; - callback= arguments[1] || function(){}; + graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri); + triples = arguments[0]; + callback= arguments[1] || function(){}; } else if(arguments.length === 3) { - triples = arguments[0]; - graph = this.rdf.createNamedNode(arguments[1]); - callback= arguments[2] || function(){}; + triples = arguments[0]; + graph = this.rdf.createNamedNode(arguments[1]); + callback= arguments[2] || function(){}; } else { - throw("The triples to insert, an optional graph and callback must be provided"); + throw("The triples to insert, an optional graph and callback must be provided"); } var query = ""; var that = this; triples.forEach(function(triple) { - query = query + that._nodeToQuery(triple.subject) + that._nodeToQuery(triple.predicate) + that._nodeToQuery(triple.object) + "."; + query = query + that._nodeToQuery(triple.subject) + that._nodeToQuery(triple.predicate) + that._nodeToQuery(triple.object) + "."; }); if(graph != null) { - query = "INSERT DATA { GRAPH " + this._nodeToQuery(graph) +" { "+ query + " } }"; + query = "INSERT DATA { GRAPH " + this._nodeToQuery(graph) +" { "+ query + " } }"; } else { - query = "INSERT DATA { " + this._nodeToQuery(graph) +" { "+ query + " }"; + query = "INSERT DATA { " + this._nodeToQuery(graph) +" { "+ query + " }"; } this.engine.execute(query, callback); - }; +}; - Store.Store.prototype._nodeToQuery = function(term) { +Store.Store.prototype._nodeToQuery = function(term) { if(term.interfaceName === 'NamedNode') { - var resolvedUri = this.rdf.resolve(term.valueOf()); - if(resolvedUri != null) { - return "<" + resolvedUri + ">"; - } else { - return "<" + term.valueOf() + ">"; - } + var resolvedUri = this.rdf.resolve(term.valueOf()); + if(resolvedUri != null) { + return "<" + resolvedUri + ">"; + } else { + return "<" + term.valueOf() + ">"; + } } else if(term.interfaceName === '') { - return term.toString(); + return term.toString(); } else { - if(term.lang != null) { - return "\""+term.valueOf()+"\"@"+term.lang; - } else if(term.datatype != null) { - return "\""+term.valueOf()+"\"^^<"+term.datatype+">"; - } - return term.toString(); - } - }; - - /** - * Removes the triples in a RDF JS Interface API Graph object from the store. - * The function receives a mandatory Graph object whose triples - * will be removed. Optionally, a URI string for a graph and a - * callback function can be passed as arguments.
- *
- * If no graph URI is specified, triples will be removed from the - * default graph.
- *
- * If the callback function is specified, it will be invoked when all the - * triples had been removed from the store. - * - * @arguments - * @param {RDFJSInterface.Graph} triples a RDF JS Interface Graph object - * @param {String} [graphURI] URI of the graph where the triples will be removed from. If it is missing, triples will be removed from the default graph - * @param {String} [callback] A callback function that will be invoked with a success notification - */ - Store.Store.prototype['delete'] = function() { + if(term.lang != null) { + return "\""+term.valueOf()+"\"@"+term.lang; + } else if(term.datatype != null) { + return "\""+term.valueOf()+"\"^^<"+term.datatype+">"; + } + return term.toString(); + } +}; + +/** + * Removes the triples in a RDF JS Interface API Graph object from the store. + * The function receives a mandatory Graph object whose triples + * will be removed. Optionally, a URI string for a graph and a + * callback function can be passed as arguments.
+ *
+ * If no graph URI is specified, triples will be removed from the + * default graph.
+ *
+ * If the callback function is specified, it will be invoked when all the + * triples had been removed from the store. + * + * @arguments + * @param {RDFJSInterface.Graph} triples a RDF JS Interface Graph object + * @param {String} [graphURI] URI of the graph where the triples will be removed from. If it is missing, triples will be removed from the default graph + * @param {String} [callback] A callback function that will be invoked with a success notification + */ +Store.Store.prototype['delete'] = function() { var graph; var triples; var callback; if(arguments.length === 1) { - triples = arguments[0]; + triples = arguments[0]; } else if(arguments.length === 2) { - graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri); - triples = arguments[0]; - callback= arguments[1] || function(){}; + graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri); + triples = arguments[0]; + callback= arguments[1] || function(){}; } else if(arguments.length === 3) { - triples = arguments[0]; - graph = this.rdf.createNamedNode(arguments[1]); - callback= arguments[2] || function(){}; + triples = arguments[0]; + graph = this.rdf.createNamedNode(arguments[1]); + callback= arguments[2] || function(){}; } else { - throw("The triples to delete, an optional graph and callback must be provided"); + throw("The triples to delete, an optional graph and callback must be provided"); } var query = ""; var that = this; triples.forEach(function(triple) { - query = query + that._nodeToQuery(triple.subject) + that._nodeToQuery(triple.predicate) + that._nodeToQuery(triple.object) + "."; + query = query + that._nodeToQuery(triple.subject) + that._nodeToQuery(triple.predicate) + that._nodeToQuery(triple.object) + "."; }); if(graph != null) { - query = "DELETE DATA { GRAPH " + this._nodeToQuery(graph) +" { "+ query + " } }"; + query = "DELETE DATA { GRAPH " + this._nodeToQuery(graph) +" { "+ query + " } }"; } else { - query = "DELETE DATA { " + this._nodeToQuery(graph) +" { "+ query + " }"; + query = "DELETE DATA { " + this._nodeToQuery(graph) +" { "+ query + " }"; } this.engine.execute(query, callback); - }; - - /** - * Removes all the triples stored in a graph. - * - * The URI of the graph and a callback function can be - * optinally passed as parameters.
- *
- * If no graph URI is specified, all triples in the - * default graph will be removed. - * - * @arguments - * @param {String} [graph] the URI of the graph the triples must be removed from - * @param {Function} [callback] a function that will be invoked with a success notification - */ - Store.Store.prototype.clear = function() { +}; + +/** + * Removes all the triples stored in a graph. + * + * The URI of the graph and a callback function can be + * optinally passed as parameters.
+ *
+ * If no graph URI is specified, all triples in the + * default graph will be removed. + * + * @arguments + * @param {String} [graph] the URI of the graph the triples must be removed from + * @param {Function} [callback] a function that will be invoked with a success notification + */ +Store.Store.prototype.clear = function() { var graph; var callback; if(arguments.length === 0) { - graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri); - var callback= function(){}; + graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri); + var callback= function(){}; } else if(arguments.length === 1) { - graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri); - callback= arguments[0] || function(){}; + graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri); + callback= arguments[0] || function(){}; } else if(arguments.length === 2) { - graph = this.rdf.createNamedNode(arguments[0]); - callback= arguments[1] || function(){}; + graph = this.rdf.createNamedNode(arguments[0]); + callback= arguments[1] || function(){}; } else { - throw("The optional graph and a callback must be provided"); + throw("The optional graph and a callback must be provided"); } var query = "CLEAR GRAPH " + this._nodeToQuery(graph); this.engine.execute(query, callback); - }; - - /** - * Boolean value determining if loading RDF must produce - * triple add events and fire callbacks.
- * Default value is false. - * - * @arguments - * @param {boolean} mustFireEvents true/false value. - */ - Store.Store.prototype.setBatchLoadEvents = function(mustFireEvents){ +}; + +/** + * Boolean value determining if loading RDF must produce + * triple add events and fire callbacks.
+ * Default value is false. + * + * @arguments + * @param {boolean} mustFireEvents true/false value. + */ +Store.Store.prototype.setBatchLoadEvents = function(mustFireEvents){ this.engine.eventsOnBatchLoad = mustFireEvents; - }; - - /** - * Registers a namespace prefix that will be automatically declared - * in all the queries.
- *
- * The prefix will also be inserte in the default RDFEnvironment object - * associated to the rdf property of the store instance. - * - * @arguments - * @param {String} ns the name space to be regsitered - * @param {String} prefix the URI fragment associated to the name space - */ - Store.Store.prototype.registerDefaultNamespace = function(ns, prefix) { +}; + +/** + * Registers a namespace prefix that will be automatically declared + * in all the queries.
+ *
+ * The prefix will also be inserte in the default RDFEnvironment object + * associated to the rdf property of the store instance. + * + * @arguments + * @param {String} ns the name space to be regsitered + * @param {String} prefix the URI fragment associated to the name space + */ +Store.Store.prototype.registerDefaultNamespace = function(ns, prefix) { this.rdf.prefixes.set(ns,prefix); this.engine.registerDefaultNamespace(ns,prefix); - }; +}; - /** - * Registers the default namespaces declared in the RDF JS Interfaces - * specification in the default Profile. - */ - Store.Store.prototype.registerDefaultProfileNamespaces = function() { +/** + * Registers the default namespaces declared in the RDF JS Interfaces + * specification in the default Profile. + */ +Store.Store.prototype.registerDefaultProfileNamespaces = function() { var defaultNsMap = this.rdf.prefixes.values(); for (var p in defaultNsMap) { - this.registerDefaultNamespace(p,defaultNsMap[p]); - } - }; - - /** - * Load triples into a graph in the store. Data can be passed directly to the method - * or a remote URI speifying where the data is located can be used.
- *
- * If the data is passed directly to the load function, the media type stating the format - * of the data must also be passed to the function.
- *
- * If an URI is passed as a parameter, the store will attempt to perform content negotiation - * with the remote server and get a representation for the RDF data matching one of the - * the RDF parsers registered in the store. In this case, the media type parameter must be - * set to the 'remote' value.
- *
- * An additional URI for the graph where the parsed data will be loaded and a callback function - * can be also passed as parameters. If no graph is specified, triples will be loaded in the - * default graph.
- *
- * By default loading data will not trigger notification through the events API. If events needs to - * be trigger, the functio setBatchLoadEvents must be invoked with a true parameter. - * - * @arguments - * @param {String} mediaType Media type (application/json, text/n3...) of the data to be parsed or the value 'remote' if a URI for the data is passed instead - * @param {String} data RDF data to be parsed and loaded or an URI where the data will be retrieved after performing content negotiation - * @param {String} [graph] Graph where the parsed triples will be inserted. If it is not specified, triples will be loaded in the default graph - * @param {Function} callback that will be invoked with a success notification and the number of triples loaded. - */ - Store.Store.prototype.load = function(){ + this.registerDefaultNamespace(p,defaultNsMap[p]); + } +}; + +/** + * Load triples into a graph in the store. Data can be passed directly to the method + * or a remote URI speifying where the data is located can be used.
+ *
+ * If the data is passed directly to the load function, the media type stating the format + * of the data must also be passed to the function.
+ *
+ * If an URI is passed as a parameter, the store will attempt to perform content negotiation + * with the remote server and get a representation for the RDF data matching one of the + * the RDF parsers registered in the store. In this case, the media type parameter must be + * set to the 'remote' value.
+ *
+ * An additional URI for the graph where the parsed data will be loaded and a callback function + * can be also passed as parameters. If no graph is specified, triples will be loaded in the + * default graph.
+ *
+ * By default loading data will not trigger notification through the events API. If events needs to + * be trigger, the functio setBatchLoadEvents must be invoked with a true parameter. + * + * @arguments + * @param {String} mediaType Media type (application/json, text/n3...) of the data to be parsed or the value 'remote' if a URI for the data is passed instead + * @param {String} data RDF data to be parsed and loaded or an URI where the data will be retrieved after performing content negotiation + * @param {String} [graph] Graph where the parsed triples will be inserted. If it is not specified, triples will be loaded in the default graph + * @param {Function} callback that will be invoked with a success notification and the number of triples loaded. + */ +Store.Store.prototype.load = function(){ var mediaType; var data; var graph; @@ -31876,397 +31312,396 @@ var options = {}; if(arguments.length === 3) { - graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri); - mediaType = arguments[0]; - data = arguments[1]; - callback= arguments[2] || function(){}; + graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri); + mediaType = arguments[0]; + data = arguments[1]; + callback= arguments[2] || function(){}; } else if(arguments.length === 4) { - mediaType = arguments[0]; - data = arguments[1]; - options = arguments[2]; - if(typeof(options) === 'string') { - graph = this.rdf.createNamedNode(options); - options = {}; - } else { - graph = this.rdf.createNamedNode(options.graph || this.engine.lexicon.defaultGraphUri); - delete options['graph']; - } - callback= arguments[3] || function(){}; + mediaType = arguments[0]; + data = arguments[1]; + options = arguments[2]; + if(typeof(options) === 'string') { + graph = this.rdf.createNamedNode(options); + options = {}; + } else { + graph = this.rdf.createNamedNode(options.graph || this.engine.lexicon.defaultGraphUri); + delete options['graph']; + } + callback= arguments[3] || function(){}; } else if(arguments.length === 2) { - throw("The mediaType of the parser, the data a callback and an optional graph must be provided"); + throw("The mediaType of the parser, the data a callback and an optional graph must be provided"); } if(mediaType === 'remote') { - data = this.rdf.createNamedNode(data); - var query = "LOAD <"+data.valueOf()+"> INTO GRAPH <"+graph.valueOf()+">"; - this.engine.execute(query, callback); + data = this.rdf.createNamedNode(data); + var query = "LOAD <"+data.valueOf()+"> INTO GRAPH <"+graph.valueOf()+">"; + this.engine.execute(query, callback); } else if(data && typeof(data)==='string' && data.indexOf('file://')=== 0) { - var parser = this.engine.rdfLoader.parsers[mediaType]; + var parser = this.engine.rdfLoader.parsers[mediaType]; - var that = this; - this.engine.rdfLoader.loadFromFile(parser, {'token':'uri', 'value':graph.valueOf()}, data, function(success, quads) { - if(success) { - that.engine.batchLoad(quads,callback); - } else { - callback(success, quads); - } - }); + var that = this; + this.engine.rdfLoader.loadFromFile(parser, {'token':'uri', 'value':graph.valueOf()}, data, function(success, quads) { + if(success) { + that.engine.batchLoad(quads,callback); + } else { + callback(success, quads); + } + }); } else { - var parser = this.engine.rdfLoader.parsers[mediaType]; - var that = this; + var parser = this.engine.rdfLoader.parsers[mediaType]; + var that = this; - this.engine.rdfLoader.tryToParse(parser, {'token':'uri', 'value':graph.valueOf()}, data, options, function(success, quads) { - if(success) { - that.engine.batchLoad(quads,callback); - } - else { - callback(success, quads); - } - }); + this.engine.rdfLoader.tryToParse(parser, {'token':'uri', 'value':graph.valueOf()}, data, options, function(success, quads) { + if(success) { + that.engine.batchLoad(quads,callback); + } else { + callback(success, quads); + } + }); } - }; - - /** - * Registers a new parser associated to the provided media type. If there is a parser already registered for - * that media type, the new parser will replace the old one.
- *
- * Parsers must implement a function *parse* accepting the data to be parsed as the - * first parameter and the destination graph URI as the second one. - * They must return an array of objects with properties: 'subject', 'predicate', 'object' - * and 'graph' containing lexical representations for these values: - *
- *
    - *
  • {literal: '"literal"'}
  • - *
  • {literal: ''"literal"^^'}
  • - *
  • {literal: '"literal"@lang'}
  • - *
  • {uri: 'uri'}
  • - *
  • {blank: '_:label'}
  • - *
- *
- * The provided media type will be used to perform content negotiation when dealing with remote - * resources, or to select the parser in the load function. - * - * @arguments - * @param {String} mediaType the media type for this parser - * @param {String} parser an object containing the *parse* function with the parser logic - */ - Store.Store.prototype.registerParser = function(mediaType, parser) { +}; + +/** + * Registers a new parser associated to the provided media type. If there is a parser already registered for + * that media type, the new parser will replace the old one.
+ *
+ * Parsers must implement a function *parse* accepting the data to be parsed as the + * first parameter and the destination graph URI as the second one. + * They must return an array of objects with properties: 'subject', 'predicate', 'object' + * and 'graph' containing lexical representations for these values: + *
+ *
    + *
  • {literal: '"literal"'}
  • + *
  • {literal: ''"literal"^^'}
  • + *
  • {literal: '"literal"@lang'}
  • + *
  • {uri: 'uri'}
  • + *
  • {blank: '_:label'}
  • + *
+ *
+ * The provided media type will be used to perform content negotiation when dealing with remote + * resources, or to select the parser in the load function. + * + * @arguments + * @param {String} mediaType the media type for this parser + * @param {String} parser an object containing the *parse* function with the parser logic + */ +Store.Store.prototype.registerParser = function(mediaType, parser) { this.engine.rdfLoader.registerParser(mediaType,parser); - }; - - /** - * Returns the URI of all the graphs currently contained - * in the store - * - * @arguments: - * @param {Function} callback function that will receive a success notification and the array of graph URIs - */ - Store.Store.prototype.registeredGraphs = function(callback) { +}; + +/** + * Returns the URI of all the graphs currently contained + * in the store + * + * @arguments: + * @param {Function} callback function that will receive a success notification and the array of graph URIs + */ +Store.Store.prototype.registeredGraphs = function(callback) { if(this.isMongodb) { - this.engine.registeredGraphs(true, function(graphs){ + this.engine.registeredGraphs(true, function(graphs){ + var acum = []; + for(var i=0; i"; - } else { - return "<" + term.valueOf() + ">"; - } + var resolvedUri = this.rdf.resolve(term.valueOf()); + if(resolvedUri != null) { + return "<" + resolvedUri + ">"; + } else { + return "<" + term.valueOf() + ">"; + } } else if(term.interfaceName === '') { - return term.toString(); + return term.toString(); } else { - return term.toString(); - } - }; - - /** - * Returns the current network transport being used by the - * the store. - * - * The default transport uses TCP sockets in the Node.js version - * and relies on jQuery in the browser version. This can be overriden - * using the setNetworkTransport function. - */ - Store.Store.prototype.getNetworkTransport = function() { + return term.toString(); + } +}; + +/** + * Returns the current network transport being used by the + * the store. + * + * The default transport uses TCP sockets in the Node.js version + * and relies on jQuery in the browser version. This can be overriden + * using the setNetworkTransport function. + */ +Store.Store.prototype.getNetworkTransport = function() { return NetworkTransport; - }; - - /** - * Sets the network transport used by the store.
- *
- * Network transport consist of an object implementing the load - * function, receiving the URI to load, a string with the value - * of the HTTP 'Accept' header for the store registered parsers, - * a callback function where the retrieved data and the success notification - * must be returned.
- *
- * Different examples with implementations of different transports can be found - * in the source code of the store: - *
    - *
  • src/js-communication/src/tcp_transport.js
  • - *
  • src/js-communication/src/ajax_transport.js
  • - *
- * @arguments - * @param networkTransportImpl object implementing the transport *load* function. - */ - Store.Store.prototype.setNetworkTransport = function(networkTransportImpl) { +}; + +/** + * Sets the network transport used by the store.
+ *
+ * Network transport consist of an object implementing the load + * function, receiving the URI to load, a string with the value + * of the HTTP 'Accept' header for the store registered parsers, + * a callback function where the retrieved data and the success notification + * must be returned.
+ *
+ * Different examples with implementations of different transports can be found + * in the source code of the store: + *
    + *
  • src/js-communication/src/tcp_transport.js
  • + *
  • src/js-communication/src/ajax_transport.js
  • + *
+ * @arguments + * @param networkTransportImpl object implementing the transport *load* function. + */ +Store.Store.prototype.setNetworkTransport = function(networkTransportImpl) { NetworkTransport = networkTransportImpl; - }; +}; - /** - * Clean-up function releasing all temporary resources held by the - * store instance. - */ - Store.Store.prototype.close = function(cb) { +/** + * Clean-up function releasing all temporary resources held by the + * store instance. + */ +Store.Store.prototype.close = function(cb) { if(cb == null) - cb = function(){}; + cb = function(){}; if(this.engine.close) - this.engine.close(cb); + this.engine.close(cb); else - cb(); - }; + cb(); +}; // end of ./src/js-store/src/store.js // imports - RDFStoreWorker = {}; - - RDFStoreWorker.observingCallbacks = {}; - - RDFStoreWorker.workerCallbacksCounter = 0; - RDFStoreWorker.workerCallbacks = {}; - RDFStoreWorker.registerCallback = function(cb) { - var nextId = ""+RDFStoreWorker.workerCallbacksCounter; - RDFStoreWorker.workerCallbacksCounter++; - RDFStoreWorker.workerCallbacks[nextId] = cb; - return nextId; - }; + RDFStoreWorker = {}; + + RDFStoreWorker.observingCallbacks = {}; + + RDFStoreWorker.workerCallbacksCounter = 0; + RDFStoreWorker.workerCallbacks = {}; + RDFStoreWorker.registerCallback = function(cb) { + var nextId = ""+RDFStoreWorker.workerCallbacksCounter; + RDFStoreWorker.workerCallbacksCounter++; + RDFStoreWorker.workerCallbacks[nextId] = cb; + return nextId; + }; - RDFStoreWorker.handleCreate = function(argsObject, cb) { - // redefine NetworkTransport + RDFStoreWorker.handleCreate = function(argsObject, cb) { + // redefine NetworkTransport - if(typeof(NetworkTransport) != 'undefined' && NetworkTransport != null) { - NetworkTransport = { - load: function(uri, graph, callback) { - var cbId = RDFStoreWorker.registerCallback(function(results){ - callback.apply(callback,results); - }); - postMessage({'fn':'workerRequest:NetworkTransport:load','callback':cbId, 'arguments':[uri,graph]}); - }, + if(typeof(NetworkTransport) != 'undefined' && NetworkTransport != null) { + NetworkTransport = { + load: function(uri, graph, callback) { + var cbId = RDFStoreWorker.registerCallback(function(results){ + callback.apply(callback,results); + }); + postMessage({'fn':'workerRequest:NetworkTransport:load','callback':cbId, 'arguments':[uri,graph]}); + }, - loadFromFile: function(parser, graph, uri, callback) { + loadFromFile: function(parser, graph, uri, callback) { + } + } } - } - } - var args = [argsObject]; - //console.log("in handling create"); - args.push(function(result){ - //console.log("created!!!"); - // Stores the store object in the worker - RDFStoreWorker.store = result; - //console.log("posting MESSAGE!"); + var args = [argsObject]; + //console.log("in handling create"); + args.push(function(result){ + //console.log("created!!!"); + // Stores the store object in the worker + RDFStoreWorker.store = result; + //console.log("posting MESSAGE!"); - postMessage({'callback':cb, 'result':'created', 'success':true}); - }); - //console.log("creating"); - Store.create.apply(Store,args) - }; - - RDFStoreWorker.receive = function(packet) { - var msg = packet.data || packet; - //console.log("RECEIVED..."); - if(msg.fn === 'workerRequestResponse') { - var cbId = msg.callback; - var callback = RDFStoreWorker.workerCallbacks[cbId]; - if(callback != null) { - delete RDFStoreWorker.workerCallbacks[cbId]; - callback(msg.results); - } - } else if(msg.fn === 'create' && msg.args !=null) { - //console.log("handling create"); - RDFStoreWorker.handleCreate(msg.args, msg.callback); - } else if(msg.fn === 'setBatchLoadEvents') { - RDFStoreWorker.store[msg.fn].apply(RDFStoreWorker.store, msg.args); - } else if(msg.fn === 'registerDefaultNamespace') { - RDFStoreWorker.store[msg.fn].apply(RDFStoreWorker.store, msg.args); - } else if(msg.fn === 'registerDefaultProfileNamespaces') { - RDFStoreWorker.store[msg.fn].apply(RDFStoreWorker.store, msg.args); - } else if((msg.fn === 'execute' || - msg.fn === 'executeWithEnvironment' || - msg.fn === 'graph'|| - msg.fn === 'node' || - msg.fn === 'clear' || - msg.fn === 'load') && msg.args != null) { - msg.args.push(function(success, result){ - //console.log("CALLBACK!"); - if(msg.callback!=null) { - postMessage({'callback':msg.callback, 'result':result, 'success':success}); - } - }); - try { - RDFStoreWorker.store[msg.fn].apply(RDFStoreWorker.store,msg.args); - } catch(e) { - console.log("Error executing method through connection"); - console.log(e); - } - } else if((msg.fn === 'insert'|| - msg.fn === 'delete') && msg.args != null) { - try { - msg.args.push(function(success, result){ - //console.log("CALLBACK!"); - if(msg.callback!=null) { - postMessage({'callback':msg.callback, 'result':result, 'success':success}); - } + postMessage({'callback':cb, 'result':'created', 'success':true}); }); - var triple; - var toWrap = msg.args[0]; - for(var i=0; i