www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

commit 53d336681bf498700b69babaefc218a490e440c0
parent b9d7992ba860092f40d8ab5affd4379e5ac51185
Author: aurimasv <aurimas.dev@gmail.com>
Date:   Wed, 25 Apr 2012 20:14:58 -0500

Tabulator v0.8 RDF parser initial commit

Diffstat:
Mchrome/content/zotero/xpcom/rdf/identity.js | 333++++++++++++++++++++++++++++++-------------------------------------------------
Mchrome/content/zotero/xpcom/rdf/match.js | 107++++++++++++++++++++++---------------------------------------------------------
Mchrome/content/zotero/xpcom/rdf/n3parser.js | 248++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Mchrome/content/zotero/xpcom/rdf/rdfparser.js | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Mchrome/content/zotero/xpcom/rdf/serialize.js | 397+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Mchrome/content/zotero/xpcom/rdf/term.js | 368+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mchrome/content/zotero/xpcom/rdf/uri.js | 46++++++++++++++++++++++++----------------------
7 files changed, 837 insertions(+), 736 deletions(-)

diff --git a/chrome/content/zotero/xpcom/rdf/identity.js b/chrome/content/zotero/xpcom/rdf/identity.js @@ -1,6 +1,6 @@ // Identity management and indexing for RDF // -// This file provides RDFIndexedFormula a formula (set of triples) which +// This file provides IndexedFormula a formula (set of triples) which // indexed by predicate, subject and object. // // It "smushes" (merges into a single node) things which are identical @@ -15,38 +15,24 @@ /*jsl:option explicit*/ // Turn on JavaScriptLint variable declaration checking -owl_ns = "http://www.w3.org/2002/07/owl#"; -link_ns = "http://www.w3.org/2006/link#"; +$rdf.IndexedFormula = function() { + +var owl_ns = "http://www.w3.org/2002/07/owl#"; +// var link_ns = "http://www.w3.org/2007/ont/link#"; /* hashString functions are used as array indeces. This is done to avoid ** conflict with existing properties of arrays such as length and map. ** See issue 139. */ -RDFLiteral.prototype.hashString = RDFLiteral.prototype.toNT; -RDFSymbol.prototype.hashString = RDFSymbol.prototype.toNT; -RDFBlankNode.prototype.hashString = RDFBlankNode.prototype.toNT; -RDFCollection.prototype.hashString = RDFCollection.prototype.toNT; - -RDFIndexedFormula.prototype = new RDFFormula(); -RDFIndexedFormula.prototype.constructor = RDFIndexedFormula; -// RDFIndexedFormula.superclass = RDFFormula.prototype; -RDFIndexedFormula.SuperClass = RDFFormula; - -RDFArrayRemove = function(a, x) { //removes all elements equal to x from a - for(var i=0; i<a.length; i++) { - if (a[i] == x) { - a.splice(i,1); - return; - } - } - throw "RDFArrayRemove: Array did not contain " + x; -}; - +$rdf.Literal.prototype.hashString = $rdf.Literal.prototype.toNT; +$rdf.Symbol.prototype.hashString = $rdf.Symbol.prototype.toNT; +$rdf.BlankNode.prototype.hashString = $rdf.BlankNode.prototype.toNT; +$rdf.Collection.prototype.hashString = $rdf.Collection.prototype.toNT; //Stores an associative array that maps URIs to functions -function RDFIndexedFormula(features) { - this.statements = []; // As in RDFFormula +$rdf.IndexedFormula = function(features) { + this.statements = []; // As in Formula this.optional = []; this.propertyActions = []; // Array of functions to call when getting statement with {s X o} //maps <uri> to [f(F,s,p,o),...] @@ -60,12 +46,10 @@ function RDFIndexedFormula(features) { this.whyIndex = []; // Array of statements with X as provenance this.index = [ this.subjectIndex, this.predicateIndex, this.objectIndex, this.whyIndex ]; this.namespaces = {} // Dictionary of namespace prefixes - if (features == undefined) features = ["sameAs", + if (features === undefined) features = ["sameAs", "InverseFunctionalProperty", "FunctionalProperty"]; // this.features = features - // Callbackify? - function handleRDFType(formula, subj, pred, obj, why) { if (formula.typeCallback != undefined) formula.typeCallback(formula, obj, why); @@ -85,36 +69,21 @@ function RDFIndexedFormula(features) { '<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>'] = [ handleRDFType ]; // Assumption: these terms are not redirected @@fixme - if (features.indexOf("sameAs") >=0) + if ($rdf.Util.ArrayIndexOf(features,"sameAs") >= 0) this.propertyActions['<http://www.w3.org/2002/07/owl#sameAs>'] = [ function(formula, subj, pred, obj, why) { + // tabulator.log.warn("Equating "+subj.uri+" sameAs "+obj.uri); //@@ formula.equate(subj,obj); return true; // true if statement given is NOT needed in the store }]; //sameAs -> equate & don't add to index -/* - function newPropertyAction(formula, pred, action) { - tabulator.log.debug("newPropertyAction: "+pred); - if (formula.propertyActions[pred] == undefined) - formula.propertyActions[pred] = []; - formula.propertyActions[pred].push(action); - // Now apply the function to to statements already in the store - var toBeFixed = formula.statementsMatching(undefined, pred, undefined); - var i; - for (i=0; i<toBeFixed.length; i++) { // NOT optimized - sort toBeFixed etc - if (action(formula, toBeFixed[i].subject, pred, toBeFixed[i].object)) { - tabulator.log.debug("newPropertyAction: NOT removing "+toBeFixed[i]); - } - } - return false; - } -*/ - if (features.indexOf("InverseFunctionalProperty") >= 0) + + if ($rdf.Util.ArrayIndexOf(features,"InverseFunctionalProperty") >= 0) this.classActions["<"+owl_ns+"InverseFunctionalProperty>"] = [ function(formula, subj, pred, obj, addFn) { return formula.newPropertyAction(subj, handle_IFP); // yes subj not pred! }]; //IFP -> handle_IFP, do add to index - if (features.indexOf("FunctionalProperty") >= 0) + if ($rdf.Util.ArrayIndexOf(features,"FunctionalProperty") >= 0) this.classActions["<"+owl_ns+"FunctionalProperty>"] = [ function(formula, subj, proj, obj, addFn) { return formula.newPropertyAction(subj, handle_FP); @@ -123,6 +92,7 @@ function RDFIndexedFormula(features) { function handle_IFP(formula, subj, pred, obj) { var s1 = formula.any(undefined, pred, obj); if (s1 == undefined) return false; // First time with this value + // tabulator.log.warn("Equating "+s1.uri+" and "+subj.uri + " because IFP "+pred.uri); //@@ formula.equate(s1, subj); return true; } //handle_IFP @@ -130,17 +100,19 @@ function RDFIndexedFormula(features) { function handle_FP(formula, subj, pred, obj) { var o1 = formula.any(subj, pred, undefined); if (o1 == undefined) return false; // First time with this value + // tabulator.log.warn("Equating "+o1.uri+" and "+obj.uri + " because FP "+pred.uri); //@@ formula.equate(o1, obj); return true ; } //handle_FP - -} /* end RDFIndexedFormula */ - +} /* end IndexedFormula */ +$rdf.IndexedFormula.prototype = new $rdf.Formula(); +$rdf.IndexedFormula.prototype.constructor = $rdf.IndexedFormula; +$rdf.IndexedFormula.SuperClass = $rdf.Formula; -RDFIndexedFormula.prototype.newPropertyAction = function newPropertyAction(pred, action) { - tabulator.log.debug("newPropertyAction: "+pred); +$rdf.IndexedFormula.prototype.newPropertyAction = function newPropertyAction(pred, action) { + //$rdf.log.debug("newPropertyAction: "+pred); var hash = pred.hashString(); if (this.propertyActions[hash] == undefined) this.propertyActions[hash] = []; @@ -154,15 +126,9 @@ RDFIndexedFormula.prototype.newPropertyAction = function newPropertyAction(pred, return done; } - - - -RDFPlainFormula = function() { return RDFIndexedFormula([]); } // No features - - -RDFIndexedFormula.prototype.setPrefixForURI = function(prefix, nsuri) { +$rdf.IndexedFormula.prototype.setPrefixForURI = function(prefix, nsuri) { //TODO:This is a hack for our own issues, which ought to be fixed post-release - //See http://dig.csail.mit.edu/cgi-bin/roundup.cgi/tabulator/issue227 + //See http://dig.csail.mit.edu/cgi-bin/roundup.cgi/$rdf/issue227 if(prefix=="tab" && this.namespaces["tab"]) { return; } @@ -170,33 +136,36 @@ RDFIndexedFormula.prototype.setPrefixForURI = function(prefix, nsuri) { } // Deprocated ... name too generic -RDFIndexedFormula.prototype.register = function(prefix, nsuri) { +$rdf.IndexedFormula.prototype.register = function(prefix, nsuri) { this.namespaces[prefix] = nsuri } -/** simplify graph in store when we realize two identifiers are equal +/** simplify graph in store when we realize two identifiers are equivalent We replace the bigger with the smaller. */ -RDFIndexedFormula.prototype.equate = function(u1, u2) { - tabulator.log.debug("Equating "+u1+" and "+u2) - +$rdf.IndexedFormula.prototype.equate = function(u1, u2) { + // tabulator.log.warn("Equating "+u1+" and "+u2); // @@ + //@@JAMBO Must canonicalize the uris to prevent errors from a=b=c + //03-21-2010 + u1 = this.canon( u1 ); + u2 = this.canon( u2 ); var d = u1.compareTerm(u2); if (!d) return true; // No information in {a = a} var big, small; if (d < 0) { // u1 less than u2 - return this.replaceWith(u2, u1); + return this.replaceWith(u2, u1); } else { - return this.replaceWith(u1, u2); + return this.replaceWith(u1, u2); } } // Replace big with small, obsoleted with obsoleting. // -RDFIndexedFormula.prototype.replaceWith = function(big, small) { - tabulator.log.debug("Replacing "+big+" with "+small) // @@ +$rdf.IndexedFormula.prototype.replaceWith = function(big, small) { + //$rdf.log.debug("Replacing "+big+" with "+small) // @@ var oldhash = big.hashString(); var newhash = small.hashString(); @@ -205,7 +174,7 @@ RDFIndexedFormula.prototype.replaceWith = function(big, small) { if (oldlist == undefined) return; // none to move var newlist = ix[newhash]; if (newlist == undefined) { - ix[newhash] = newlist; + ix[newhash] = oldlist; } else { ix[newhash] = oldlist.concat(newlist); } @@ -219,28 +188,35 @@ RDFIndexedFormula.prototype.replaceWith = function(big, small) { this.redirections[oldhash] = small; if (big.uri) { - if (this.aliases[newhash] == undefined) - this.aliases[newhash] = []; - this.aliases[newhash].push(big); // Back link - - this.add(small, this.sym('http://www.w3.org/2006/link#uri'), big.uri) - - // If two things are equal, and one is requested, we should request the other. - if (this.sf) { - this.sf.nowKnownAs(big, small) - } - + //@@JAMBO: must update redirections,aliases from sub-items, too. + if (this.aliases[newhash] == undefined) + this.aliases[newhash] = []; + this.aliases[newhash].push(big); // Back link + + if( this.aliases[oldhash] ) { + for( var i = 0; i < this.aliases[oldhash].length; i++ ) { + this.redirections[this.aliases[oldhash][i].hashString()] = small; + this.aliases[newhash].push(this.aliases[oldhash][i]); + } + } + + this.add(small, this.sym('http://www.w3.org/2007/ont/link#uri'), big.uri) + + // If two things are equal, and one is requested, we should request the other. + if (this.sf) { + this.sf.nowKnownAs(big, small) + } } moveIndex(this.classActions); moveIndex(this.propertyActions); - tabulator.log.debug("Equate done. "+big+" to be known as "+small) + //$rdf.log.debug("Equate done. "+big+" to be known as "+small) return true; // true means the statement does not need to be put in }; // Return the symbol with canonical URI as smushed -RDFIndexedFormula.prototype.canon = function(term) { +$rdf.IndexedFormula.prototype.canon = function(term) { if (term == undefined) return term; var y = this.redirections[term.hashString()]; if (y == undefined) return term; @@ -248,7 +224,7 @@ RDFIndexedFormula.prototype.canon = function(term) { } // Compare by canonical URI as smushed -RDFIndexedFormula.prototype.sameThings = function(x, y) { +$rdf.IndexedFormula.prototype.sameThings = function(x, y) { if (x.sameTerm(y)) return true; var x1 = this.canon(x); // alert('x1='+x1); @@ -260,7 +236,7 @@ RDFIndexedFormula.prototype.sameThings = function(x, y) { } // A list of all the URIs by which this thing is known -RDFIndexedFormula.prototype.uris = function(term) { +$rdf.IndexedFormula.prototype.uris = function(term) { var cterm = this.canon(term) var terms = this.aliases[cterm.hashString()]; if (!cterm.uri) return [] @@ -277,27 +253,31 @@ RDFIndexedFormula.prototype.uris = function(term) { // function RDFMakeTerm(formula,val, canonicalize) { if (typeof val != 'object') { - if (typeof val == 'string') - return new RDFLiteral(val); + if (typeof val == 'string') + return new $rdf.Literal(val); if (typeof val == 'number') - return new RDFLiteral(val); // @@ differet types + return new $rdf.Literal(val); // @@ differet types if (typeof val == 'boolean') - return new RDFLiteral(val?"1":"0", undefined, - RDFSymbol.prototype.XSDboolean); - else if (typeof val == 'number') - return new RDFLiteral(''+val); // @@ datatypes - else if (typeof val == 'undefined') - return undefined; - else // @@ add converting of dates and numbers - throw "Can't make Term from " + val + " of type " + typeof val; + return new $rdf.Literal(val?"1":"0", undefined, + $rdf.Symbol.prototype.XSDboolean); + else if (typeof val == 'number') + return new $rdf.Literal(''+val); // @@ datatypes + else if (typeof val == 'undefined') + return undefined; + else // @@ add converting of dates and numbers + throw "Can't make Term from " + val + " of type " + typeof val; } return val; } -// add a triple to the store -RDFIndexedFormula.prototype.add = function(subj, pred, obj, why) { +// Add a triple to the store +// +// Returns the statement added +// (would it be better to return the original formula for chaining?) +// +$rdf.IndexedFormula.prototype.add = function(subj, pred, obj, why) { var actions, st; - if (why == undefined) why = this.fetcher ? this.fetcher.appNode: kb.sym("chrome:theSession"); //system generated + if (why == undefined) why = this.fetcher ? this.fetcher.appNode: this.sym("chrome:theSession"); //system generated //defined in source.js, is this OK with identity.js only user? subj = RDFMakeTerm(this, subj); pred = RDFMakeTerm(this, pred); @@ -307,23 +287,7 @@ RDFIndexedFormula.prototype.add = function(subj, pred, obj, why) { var hash = [ this.canon(subj).hashString(), this.canon(pred).hashString(), this.canon(obj).hashString(), this.canon(why).hashString()]; -/* // Removed TimBL 2007-01-06 - // Check we don't already know it -- esp when working with dbview - // db view has many documents with the same triple - a waste. - // but is we want to be able to edit documents, we must maintain the original - // triples from each one. We might occasionally want to mutiple provences too - // for a full Truth Management System. Maybe this should be run-time option. - st = this.anyStatementMatching(subj,pred,obj) // @@@@@@@ temp fix <====WATCH OUT! - It is general necessary to know when data has come from >1 place. - Maybe this should be a mode? -*/ - // This is wasting time and shouldn't happen at all - //st = this.anyStatementMatching(subj,pred,obj,why) // Avoid duplicates - //if (st != undefined) return; // already in store - - - - // tabulator.log.debug("\nActions for "+s+" "+p+" "+o+". size="+this.statements.length) + if (this.predicateCallback != undefined) this.predicateCallback(this, pred, why); @@ -338,24 +302,24 @@ RDFIndexedFormula.prototype.add = function(subj, pred, obj, why) { } //If we are tracking provenanance, every thing should be loaded into the store - //if (done) return new RDFStatement(subj, pred, obj, why); // Don't put it in the store + //if (done) return new Statement(subj, pred, obj, why); // Don't put it in the store // still return this statement for owl:sameAs input - var st = new RDFStatement(subj, pred, obj, why); + var st = new $rdf.Statement(subj, pred, obj, why); for (var i=0; i<4; i++) { var ix = this.index[i]; var h = hash[i]; if (ix[h] == undefined) ix[h] = []; - ix[h].push(st); // Set of things with this as subject + ix[h].push(st); // Set of things with this as subject, etc } - tabulator.log.debug("ADDING {"+subj+" "+pred+" "+obj+"} "+why); + //$rdf.log.debug("ADDING {"+subj+" "+pred+" "+obj+"} "+why); this.statements.push(st); return st; }; //add // Find out whether a given URI is used as symbol in the formula -RDFIndexedFormula.prototype.mentionsURI = function(uri) { +$rdf.IndexedFormula.prototype.mentionsURI = function(uri) { var hash = '<' + uri + '>'; return (!!this.subjectIndex[hash] || !!this.objectIndex[hash] || !!this.predicateIndex[hash]); @@ -363,15 +327,15 @@ RDFIndexedFormula.prototype.mentionsURI = function(uri) { // Find an unused id for a file being edited: return a symbol // (Note: Slow iff a lot of them -- could be O(log(k)) ) -RDFIndexedFormula.prototype.nextSymbol = function(doc) { +$rdf.IndexedFormula.prototype.nextSymbol = function(doc) { for(var i=0;;i++) { var uri = doc.uri + '#n' + i; - if (!this.mentionsURI(uri)) return kb.sym(uri); + if (!this.mentionsURI(uri)) return this.sym(uri); } } -RDFIndexedFormula.prototype.anyStatementMatching = function(subj,pred,obj,why) { +$rdf.IndexedFormula.prototype.anyStatementMatching = function(subj,pred,obj,why) { var x = this.statementsMatching(subj,pred,obj,why,true); if (!x || x == []) return undefined; return x[0]; @@ -380,8 +344,8 @@ RDFIndexedFormula.prototype.anyStatementMatching = function(subj,pred,obj,why) { // Return statements matching a pattern // ALL CONVENIENCE LOOKUP FUNCTIONS RELY ON THIS! -RDFIndexedFormula.prototype.statementsMatching = function(subj,pred,obj,why,justOne) { - tabulator.log.debug("Matching {"+subj+" "+pred+" "+obj+"}"); +$rdf.IndexedFormula.prototype.statementsMatching = function(subj,pred,obj,why,justOne) { + //$rdf.log.debug("Matching {"+subj+" "+pred+" "+obj+"}"); var pat = [ subj, pred, obj, why ]; var pattern = []; @@ -397,10 +361,16 @@ RDFIndexedFormula.prototype.statementsMatching = function(subj,pred,obj,why,just hash[p] = pattern[p].hashString(); } } - if (given.length == 0) return this.statements; // Easy + if (given.length == 0) { + return this.statements; + } if (given.length == 1) { // Easy too, we have an index for that var p = given[0]; var list = this.index[p][hash[p]]; + if(list && justOne) { + if(list.length>1) + list = list.slice(0,1); + } return list == undefined ? [] : list; } @@ -437,29 +407,33 @@ RDFIndexedFormula.prototype.statementsMatching = function(subj,pred,obj,why,just } if (st != null) results.push(st); } + + if(justOne) { + if(results.length>1) + results = results.slice(0,1); + } return results; }; // statementsMatching - /** remove a particular statement from the bank **/ -RDFIndexedFormula.prototype.remove = function (st) { - tabulator.log.debug("entering remove w/ st=" + st); +$rdf.IndexedFormula.prototype.remove = function (st) { + //$rdf.log.debug("entering remove w/ st=" + st); var term = [ st.subject, st.predicate, st.object, st.why]; for (var p=0; p<4; p++) { var c = this.canon(term[p]); var h = c.hashString(); if (this.index[p][h] == undefined) { - tabulator.log.warn ("Statement removal: no index '+p+': "+st); + //$rdf.log.warn ("Statement removal: no index '+p+': "+st); } else { - RDFArrayRemove(this.index[p][h], st); + $rdf.Util.RDFArrayRemove(this.index[p][h], st); } } - RDFArrayRemove(this.statements, st); + $rdf.Util.RDFArrayRemove(this.statements, st); }; //remove /** remove all statements matching args (within limit) **/ -RDFIndexedFormula.prototype.removeMany = function (subj, pred, obj, why, limit) { - tabulator.log.debug("entering removeMany w/ subj,pred,obj,why,limit = " + subj +", "+ pred+", " + obj+", " + why+", " + limit); +$rdf.IndexedFormula.prototype.removeMany = function (subj, pred, obj, why, limit) { + //$rdf.log.debug("entering removeMany w/ subj,pred,obj,why,limit = " + subj +", "+ pred+", " + obj+", " + why+", " + limit); var sts = this.statementsMatching (subj, pred, obj, why, false); //This is a subtle bug that occcured in updateCenter.js too. //The fact is, this.statementsMatching returns this.whyIndex instead of a copy of it @@ -468,56 +442,19 @@ RDFIndexedFormula.prototype.removeMany = function (subj, pred, obj, why, limit) var statements = []; for (var i=0;i<sts.length;i++) statements.push(sts[i]); if (limit) statements = statements.slice(0, limit); - for (var st in statements) this.remove(statements[st]); + for (var i=0;i<statements.length;i++) this.remove(statements[i]); }; //removeMany -/** Load a resorce into the store **/ - -RDFIndexedFormula.prototype.load = function(url) { - // get the XML - var xhr = Util.XMLHTTPFactory(); // returns a new XMLHttpRequest, or ActiveX XMLHTTP object - if (xhr.overrideMimeType) { - xhr.overrideMimeType("text/xml"); - } - - // Get privileges for cross-domain web access - if(!isExtension) { - try { - Util.enablePrivilege("UniversalXPConnect UniversalBrowserRead") - } catch(e) { - throw ("Failed to get privileges: (see http://dig.csail.mit.edu/2005/ajar/ajaw/Privileges.html)" + e) - } - } - - xhr.open("GET", url, false); // Synchronous - xhr.send(""); - - // Get XML DOM Tree - - var nodeTree = xhr.responseXML; - if (nodeTree === null && xhr.responseText !== null) { - // Only if the server fails to set Content-Type: text/xml AND xmlhttprequest doesn't have the overrideMimeType method - nodeTree = (new DOMParser()).parseFromString(xhr.responseText, 'text/xml'); - } - - // Get RDF statements fromm XML - - // must be an XML document node tree - var parser = new RDFParser(this); - parser.parse(nodeTree,url); -} - - /** Utility**/ /* @method: copyTo - @discription: replace @template with @target and add appropriate triples (no triple removed) + @description: replace @template with @target and add appropriate triples (no triple removed) one-direction replication */ -RDFIndexedFormula.prototype.copyTo = function(template,target,flags){ +$rdf.IndexedFormula.prototype.copyTo = function(template,target,flags){ if (!flags) flags=[]; var statList=this.statementsMatching(template); - if (flags.indexOf('two-direction')!=-1) + if ($rdf.Util.ArrayIndexOf(flags,'two-direction')!=-1) statList.concat(this.statementsMatching(undefined,undefined,template)); for (var i=0;i<statList.length;i++){ var st=statList[i]; @@ -530,64 +467,50 @@ RDFIndexedFormula.prototype.copyTo = function(template,target,flags){ case 'collection': this.add(target,st.predicate,st.object.copy(this)); } - if (flags.indexOf('delete')!=-1) this.remove(st); + if ($rdf.Util.ArrayIndexOf(flags,'delete')!=-1) this.remove(st); } }; //for the case when you alter this.value (text modified in userinput.js) -RDFLiteral.prototype.copy = function(){ - return new RDFLiteral(this.value,this.lang,this.datatype); +$rdf.Literal.prototype.copy = function(){ + return new $rdf.Literal(this.value,this.lang,this.datatype); }; -RDFBlankNode.prototype.copy = function(formula){ //depends on the formula - var bnodeNew=new RDFBlankNode(); +$rdf.BlankNode.prototype.copy = function(formula){ //depends on the formula + var bnodeNew=new $rdf.BlankNode(); formula.copyTo(this,bnodeNew); return bnodeNew; } /** Full N3 bits -- placeholders only to allow parsing, no functionality! **/ -RDFIndexedFormula.prototype.newUniversal = function(uri) { +$rdf.IndexedFormula.prototype.newUniversal = function(uri) { var x = this.sym(uri); if (!this._universalVariables) this._universalVariables = []; this._universalVariables.push(x); return x; } -RDFIndexedFormula.prototype.newExistential = function(uri) { +$rdf.IndexedFormula.prototype.newExistential = function(uri) { if (!uri) return this.bnode(); var x = this.sym(uri); return this.declareExistential(x); } -RDFIndexedFormula.prototype.declareExistential = function(x) { +$rdf.IndexedFormula.prototype.declareExistential = function(x) { if (!this._existentialVariables) this._existentialVariables = []; this._existentialVariables.push(x); return x; } -RDFIndexedFormula.prototype.formula = function(features) { - return new RDFIndexedFormula(features); +$rdf.IndexedFormula.prototype.formula = function(features) { + return new $rdf.IndexedFormula(features); } -RDFIndexedFormula.prototype.close = function() { +$rdf.IndexedFormula.prototype.close = function() { return this; } -RDFIndexedFormula.prototype.hashString = RDFIndexedFormula.prototype.toNT; - -///////////////////////////// Provenance tracking -// -// Where did this statement come from? -// - -/* -RDFStatement.prototype.original = function() { - for (var st = this;; st = st.why.premis[0]) { - if (st.why.termType && st.why.termType== 'symbol') - return this; // This statement came from a document - } -} -*/ - +$rdf.IndexedFormula.prototype.hashString = $rdf.IndexedFormula.prototype.toNT; +return $rdf.IndexedFormula; +}(); // ends - diff --git a/chrome/content/zotero/xpcom/rdf/match.js b/chrome/content/zotero/xpcom/rdf/match.js @@ -6,74 +6,34 @@ // We retpresent a set as an associative array whose value for // each member is set to true. -/* Not used, bogus. See identity.js for the ones really used. -RDFFormula.prototype.statementsMatching = function(s,p,o,w) { - var results = [] - var i - var ls = this.statements.length - for (i=0; i<ls; i++) { - var st = this.statements[i] - if (RDFTermMatch(p, st.predicate) && // first as simplest - RDFTermMatch(s, st.subject) && - RDFTermMatch(o, st.object) && - RDFTermMatch(w, st.why)) { - results[st] = true @@@@ sould use numeric indexed array - } - - } - return results -} - -RDFFormula.prototype.anyStatementMatching = function(s,p,o,w) { - var ls = this.statements.length - var i - for (i=0; i<ls; i++) { - var st = this.statements[i] - if (RDFTermMatch(p, st.predicate) && // first as simplest - RDFTermMatch(s, st.subject) && - RDFTermMatch(o, st.object) && - RDFTermMatch(w, st.why)) { - return st - } - - } - return undefined -} -*/ - -function RDFTermMatch(pattern, term) { - if (typeof pattern == 'undefined') return true; - return pattern.sameTerm(term) -} - -RDFSymbol.prototype.sameTerm = function(other) { +$rdf.Symbol.prototype.sameTerm = function(other) { if (!other) { return false } return ((this.termType == other.termType) && (this.uri == other.uri)) } -RDFBlankNode.prototype.sameTerm = function(other) { +$rdf.BlankNode.prototype.sameTerm = function(other) { if (!other) { return false } return ((this.termType == other.termType) && (this.id == other.id)) } -RDFLiteral.prototype.sameTerm = function(other) { +$rdf.Literal.prototype.sameTerm = function(other) { if (!other) { return false } return ((this.termType == other.termType) && (this.value == other.value) && (this.lang == other.lang) && ((!this.datatype && !other.datatype) - || this.datatype.sameTerm(other.datatype))) + || (this.datatype && this.datatype.sameTerm(other.datatype)))) } -RDFVariable.prototype.sameTerm = function (other) { +$rdf.Variable.prototype.sameTerm = function (other) { if (!other) { return false } return((this.termType == other.termType) && (this.uri == other.uri)) } -RDFCollection.prototype.sameTerm = RDFBlankNode.prototype.sameTerm +$rdf.Collection.prototype.sameTerm = $rdf.BlankNode.prototype.sameTerm -RDFFormula.prototype.sameTerm = function (other) { +$rdf.Formula.prototype.sameTerm = function (other) { return this.hashString() == other.hashString(); } // Comparison for ordering @@ -85,18 +45,16 @@ RDFFormula.prototype.sameTerm = function (other) { // arbitrary: we want the value actually used to be the literal // (or list or formula). -RDFLiteral.prototype.classOrder = 1 -// RDFList.prototype.classOrder = 2 -// RDFSet.prototype.classOrder = 3 -RDFCollection.prototype.classOrder = 3 -RDFFormula.prototype.classOrder = 4 -RDFSymbol.prototype.classOrder = 5 -RDFBlankNode.prototype.classOrder = 6 +$rdf.Literal.prototype.classOrder = 1 +$rdf.Collection.prototype.classOrder = 3 +$rdf.Formula.prototype.classOrder = 4 +$rdf.Symbol.prototype.classOrder = 5 +$rdf.BlankNode.prototype.classOrder = 6 // Compaisons return sign(self - other) // Literals must come out before terms for smushing -RDFLiteral.prototype.compareTerm = function(other) { +$rdf.Literal.prototype.compareTerm = function(other) { if (this.classOrder < other.classOrder) return -1 if (this.classOrder > other.classOrder) return +1 if (this.value < other.value) return -1 @@ -104,7 +62,7 @@ RDFLiteral.prototype.compareTerm = function(other) { return 0 } -RDFSymbol.prototype.compareTerm = function(other) { +$rdf.Symbol.prototype.compareTerm = function(other) { if (this.classOrder < other.classOrder) return -1 if (this.classOrder > other.classOrder) return +1 if (this.uri < other.uri) return -1 @@ -112,7 +70,7 @@ RDFSymbol.prototype.compareTerm = function(other) { return 0 } -RDFBlankNode.prototype.compareTerm = function(other) { +$rdf.BlankNode.prototype.compareTerm = function(other) { if (this.classOrder < other.classOrder) return -1 if (this.classOrder > other.classOrder) return +1 if (this.id < other.id) return -1 @@ -120,14 +78,14 @@ RDFBlankNode.prototype.compareTerm = function(other) { return 0 } -RDFCollection.prototype.compareTerm = RDFBlankNode.prototype.compareTerm +$rdf.Collection.prototype.compareTerm = $rdf.BlankNode.prototype.compareTerm // Convenience routines // Only one of s p o can be undefined, and w is optional. -RDFFormula.prototype.each = function(s,p,o,w) { +$rdf.Formula.prototype.each = function(s,p,o,w) { var results = [] - var st, sts = this.statementsMatching(s,p,o,w) + var st, sts = this.statementsMatching(s,p,o,w,false) var i, n=sts.length if (typeof s == 'undefined') { for (i=0; i<n; i++) {st=sts[i]; results.push(st.subject)} @@ -141,7 +99,7 @@ RDFFormula.prototype.each = function(s,p,o,w) { return results } -RDFFormula.prototype.any = function(s,p,o,w) { +$rdf.Formula.prototype.any = function(s,p,o,w) { var st = this.anyStatementMatching(s,p,o,w) if (typeof st == 'undefined') return undefined; @@ -152,27 +110,20 @@ RDFFormula.prototype.any = function(s,p,o,w) { return undefined } -RDFFormula.prototype.the = function(s,p,o,w) { +$rdf.Formula.prototype.holds = function(s,p,o,w) { + var st = this.anyStatementMatching(s,p,o,w) + if (typeof st == 'undefined') return false; + return true; +} + +$rdf.Formula.prototype.the = function(s,p,o,w) { // the() should contain a check there is only one var x = this.any(s,p,o,w) if (typeof x == 'undefined') - tabulator.log.error("No value found for the(){" + s + " " + p + " " + o + "}.") + $rdf.log.error("No value found for the(){" + s + " " + p + " " + o + "}.") return x } -RDFFormula.prototype.whether = function(s,p,o,w) { - return this.statementsMatching(s,p,o,w).length; -} - -// Not a method. For use in sorts -function RDFComparePredicateObject(self, other) { - var x = self.predicate.compareTerm(other.predicate) - if (x !=0) return x - return self.object.compareTerm(other.object) -} -function RDFComparePredicateSubject(self, other) { - var x = self.predicate.compareTerm(other.predicate) - if (x !=0) return x - return self.subject.compareTerm(other.subject) +$rdf.Formula.prototype.whether = function(s,p,o,w) { + return this.statementsMatching(s,p,o,w,false).length; } -// ends diff --git a/chrome/content/zotero/xpcom/rdf/n3parser.js b/chrome/content/zotero/xpcom/rdf/n3parser.js @@ -1,5 +1,74 @@ -// Things we need to define to make converted pythn code work in js -// environment of tabulator +/** +* +* UTF-8 data encode / decode +* http://www.webtoolkit.info/ +* +**/ + +$rdf.N3Parser = function () { + +function hexify(str) { // also used in parser + return encodeURI(str); +} + +var Utf8 = { + + // public method for url encoding + encode : function (string) { + string = string.replace(/\r\n/g,"\n"); + var utftext = ""; + + for (var n = 0; n < string.length; n++) { + + var c = string.charCodeAt(n); + + if (c < 128) { + utftext += String.fromCharCode(c); + } + else if((c > 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + + } + + return utftext; + }, + + // public method for url decoding + decode : function (utftext) { + var string = ""; + var i = 0; + + while ( i < utftext.length ) { + + var c = utftext.charCodeAt(i); + if (c < 128) { + string += String.fromCharCode(c); + i++; + } + else if((c > 191) && (c < 224)) { + string += String.fromCharCode(((c & 31) << 6) + | (utftext.charCodeAt(i+1) & 63)); + i += 2; + } + else { + string += String.fromCharCode(((c & 15) << 12) + | ((utftext.charCodeAt(i+1) & 63) << 6) + | (utftext.charCodeAt(i+2) & 63)); + i += 3; + } + } + return string; + } + +}// Things we need to define to make converted pythn code work in js +// environment of $rdf var RDFSink_forSomeSym = "http://www.w3.org/2000/10/swap/log#forSome"; var RDFSink_forAllSym = "http://www.w3.org/2000/10/swap/log#forAll"; @@ -7,27 +76,27 @@ var Logic_NS = "http://www.w3.org/2000/10/swap/log#"; // pyjs seems to reference runtime library which I didn't find -pyjslib_Tuple = function(theList) { return theList }; +var pyjslib_Tuple = function(theList) { return theList }; -pyjslib_List = function(theList) { return theList }; +var pyjslib_List = function(theList) { return theList }; -pyjslib_Dict = function(listOfPairs) { +var pyjslib_Dict = function(listOfPairs) { if (listOfPairs.length > 0) throw "missing.js: oops nnonempty dict not imp"; return []; } -pyjslib_len = function(s) { return s.length } +var pyjslib_len = function(s) { return s.length } -pyjslib_slice = function(str, i, j) { +var pyjslib_slice = function(str, i, j) { if (typeof str.slice == 'undefined') throw '@@ mising.js: No .slice function for '+str+' of type '+(typeof str) if ((typeof j == 'undefined') || (j ==null)) return str.slice(i); return str.slice(i, j) // @ exactly the same spec? } -StopIteration = Error('dummy error stop iteration') +var StopIteration = Error('dummy error stop iteration'); -pyjslib_Iterator = function(theList) { +var pyjslib_Iterator = function(theList) { this.last = 0; this.li = theList; this.next = function() { @@ -35,43 +104,54 @@ pyjslib_Iterator = function(theList) { return this.li[this.last++]; } return this; -} +}; -ord = function(str) { +var ord = function(str) { return str.charCodeAt(0) } -string_find = function(str, s) { +var string_find = function(str, s) { return str.indexOf(s) } -assertFudge = function(condition, desc) { +var assertFudge = function(condition, desc) { if (condition) return; if (desc) throw "python Assertion failed: "+desc; throw "(python) Assertion failed."; } -stringFromCharCode = function(uesc) { +var stringFromCharCode = function(uesc) { return String.fromCharCode(uesc); } +String.prototype.encode = function(encoding) { + if (encoding != 'utf-8') throw "UTF8_converter: can only do utf-8" + return Utf8.encode(this); +} +String.prototype.decode = function(encoding) { + if (encoding != 'utf-8') throw "UTF8_converter: can only do utf-8" + //return Utf8.decode(this); + return this; +} + + -uripath_join = function(base, given) { - return Util.uri.join(given, base) // sad but true +var uripath_join = function(base, given) { + return $rdf.Util.uri.join(given, base) // sad but true } var becauseSubexpression = null; // No reason needed var diag_tracking = 0; var diag_chatty_flag = 0; -diag_progress = function(str) { tabulator.log.debug(str); } +var diag_progress = function(str) { /*$rdf.log.debug(str);*/ } // why_BecauseOfData = function(doc, reason) { return doc }; -RDF_type_URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"; -DAML_sameAs_URI = "http://www.w3.org/2002/07/owl#sameAs"; +var RDF_type_URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"; +var DAML_sameAs_URI = "http://www.w3.org/2002/07/owl#sameAs"; /* function SyntaxError(details) { @@ -235,7 +315,7 @@ __SinkParser.prototype.feed = function(octets) { So if there is more data to feed to the parser, it should be straightforward to recover.*/ - var str = octets; + var str = octets.decode("utf-8"); var i = 0; while ((i >= 0)) { var j = this.skipSpace(str, i); @@ -267,18 +347,17 @@ __SinkParser.prototype.tok = function(tok, str, i) { /* Check for keyword. Space must have been stripped on entry and we must not be at end of file.*/ - var whitespace = "\t\n\v\f\r "; if ((pyjslib_slice(str, i, ( i + 1 ) ) == "@")) { var i = ( i + 1 ) ; } else { - if ((this.keywords.indexOf(tok) < 0)) { + if (($rdf.Util.ArrayIndexOf(this.keywords,tok) < 0)) { return -1; } } var k = ( i + pyjslib_len(tok) ) ; - if ((pyjslib_slice(str, i, k) == tok) && (_notQNameChars.indexOf(str[k]) >= 0)) { + if ((pyjslib_slice(str, i, k) == tok) && (_notQNameChars.indexOf(str.charAt(k)) >= 0)) { return k; } else { @@ -320,7 +399,7 @@ __SinkParser.prototype.directive = function(str, i) { var x = __x.next(); - if ((this._variables.indexOf(x) < 0) || (this._parentVariables.indexOf(x) >= 0)) { + if ($rdf.Util.ArrayIndexOf(this._variables,x) < 0 || ($rdf.Util.ArrayIndexOf(this._parentVariables,x) >= 0)) { this._variables[x] = ( this._context.newUniversal(x)); } @@ -862,7 +941,7 @@ __SinkParser.prototype.commaSeparatedList = function(str, j, res, ofUris) { throw BadSyntax(this._thisDoc, this.lines, str, i, "EOF found expecting comma sep list"); return i; } - if ((str[i] == ".")) { + if ((str.charAt(i) == ".")) { return j; } if (ofUris) { @@ -965,7 +1044,7 @@ __SinkParser.prototype.uri_ref2 = function(str, i, res) { } } var symb = this._store.sym( ( ns + ln ) ); - if ((this._variables.indexOf(symb) >= 0)) { + if (($rdf.Util.ArrayIndexOf(this._variables, symb) >= 0)) { res.push(this._variables[symb]); } else { @@ -977,7 +1056,7 @@ __SinkParser.prototype.uri_ref2 = function(str, i, res) { if ((i < 0)) { return -1; } - if ((str[i] == "?")) { + if ((str.charAt(i) == "?")) { var v = new pyjslib_List([]); var j = this.variable(str, i, v); if ((j > 0)) { @@ -986,11 +1065,11 @@ __SinkParser.prototype.uri_ref2 = function(str, i, res) { } return -1; } - else if ((str[i] == "<")) { + else if ((str.charAt(i) == "<")) { var i = ( i + 1 ) ; var st = i; while ((i < pyjslib_len(str))) { - if ((str[i] == ">")) { + if ((str.charAt(i) == ">")) { var uref = pyjslib_slice(str, st, i); if (this._baseURI) { var uref = uripath_join(this._baseURI, uref); @@ -1002,7 +1081,7 @@ __SinkParser.prototype.uri_ref2 = function(str, i, res) { var uref = ( uref + "#" ) ; } var symb = this._store.sym(uref); - if ((this._variables.indexOf(symb) >= 0)) { + if (($rdf.Util.ArrayIndexOf(this._variables,symb) >= 0)) { res.push(this._variables[symb]); } else { @@ -1020,7 +1099,7 @@ __SinkParser.prototype.uri_ref2 = function(str, i, res) { if ((j < 0)) { return -1; } - if ((this.keywords.indexOf(v[0]) >= 0)) { + if (($rdf.Util.ArrayIndexOf(this.keywords, v[0]) >= 0)) { throw BadSyntax(this._thisDoc, this.lines, str, i, ( ( "Keyword \"" + v[0] ) + "\" not allowed here." ) ); } res.push(this._store.sym( ( this._bindings[""] + v[0] ) )); @@ -1034,28 +1113,24 @@ __SinkParser.prototype.skipSpace = function(str, i) { /* Skip white space, newlines and comments. return -1 if EOF, else position of first non-ws character*/ - - while (1) { - eol.lastIndex = 0; - var m = eol.exec(str.slice(i)); - if ((m == null)) { - break; - } - this.lines = ( this.lines + 1 ) ; - i += eol.lastIndex; - this.previousLine = this.startOfLine; - this.startOfLine = i; - tabulator.log.debug( ( ( ( "N3 line " + this.lines ) + " " ) + str.slice(this.previousLine, this.startOfLine) ) ); - } - ws.lastIndex = 0; - var m = ws.exec(str.slice(i)); - if ((m != null) && (m[0] != "")) { - i += ws.lastIndex; - } - if ((i == pyjslib_len(str))) { + var tmp = str; + var whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000'; + for (var j = (i ? i : 0); j < str.length; j++) { + if (whitespace.indexOf(str.charAt(j)) === -1) { + if( str.charAt(j)==='#' ) { + str = str.slice(i).replace(/^[^\n]*\n/,""); + i=0; + j=-1; + } else { + break; + } + } + } + val = (tmp.length - str.length) + j; + if( val === tmp.length ) { return -1; } - return i; + return val; }; __SinkParser.prototype.variable = function(str, i, res) { /* @@ -1071,11 +1146,11 @@ __SinkParser.prototype.variable = function(str, i, res) { } var j = ( j + 1 ) ; var i = j; - if (("0123456789-".indexOf(str[j]) >= 0)) { - throw BadSyntax(this._thisDoc, this.lines, str, j, ( ( "Varible name can't start with '" + str[j] ) + "s'" ) ); + if (("0123456789-".indexOf(str.charAt(j)) >= 0)) { + throw BadSyntax(this._thisDoc, this.lines, str, j, ( ( "Varible name can't start with '" + str.charAt(j) ) + "s'" ) ); return -1; } - while ((i < pyjslib_len(str)) && (_notNameChars.indexOf(str[i]) < 0)) { + while ((i < pyjslib_len(str)) && (_notNameChars.indexOf(str.charAt(i)) < 0)) { var i = ( i + 1 ) ; } if ((this._parentContext == null)) { @@ -1093,7 +1168,7 @@ __SinkParser.prototype.bareWord = function(str, i, res) { if ((j < 0)) { return -1; } - var ch = str[j]; + var ch = str.charAt(j); if (("0123456789-".indexOf(ch) >= 0)) { return -1; } @@ -1101,7 +1176,7 @@ __SinkParser.prototype.bareWord = function(str, i, res) { return -1; } var i = j; - while ((i < pyjslib_len(str)) && (_notNameChars.indexOf(str[i]) < 0)) { + while ((i < pyjslib_len(str)) && (_notNameChars.indexOf(str.charAt(i)) < 0)) { var i = ( i + 1 ) ; } res.push(pyjslib_slice(str, j, i)); @@ -1119,7 +1194,7 @@ __SinkParser.prototype.qname = function(str, i, res) { if ((i < 0)) { return -1; } - var c = str[i]; + var c = str.charAt(i); if (("0123456789-+".indexOf(c) >= 0)) { return -1; } @@ -1127,7 +1202,7 @@ __SinkParser.prototype.qname = function(str, i, res) { var ln = c; var i = ( i + 1 ) ; while ((i < pyjslib_len(str))) { - var c = str[i]; + var c = str.charAt(i); if ((_notNameChars.indexOf(c) < 0)) { var ln = ( ln + c ) ; var i = ( i + 1 ) ; @@ -1140,12 +1215,12 @@ __SinkParser.prototype.qname = function(str, i, res) { else { var ln = ""; } - if ((i < pyjslib_len(str)) && (str[i] == ":")) { + if ((i < pyjslib_len(str)) && (str.charAt(i) == ":")) { var pfx = ln; var i = ( i + 1 ) ; var ln = ""; while ((i < pyjslib_len(str))) { - var c = str[i]; + var c = str.charAt(i); if ((_notNameChars.indexOf(c) < 0)) { var ln = ( ln + c ) ; var i = ( i + 1 ) ; @@ -1158,7 +1233,7 @@ __SinkParser.prototype.qname = function(str, i, res) { return i; } else { - if (ln && this.keywordsSet && (this.keywords.indexOf(ln) < 0)) { + if (ln && this.keywordsSet && ($rdf.Util.ArrayIndexOf(this.keywords, ln) < 0)) { res.push(new pyjslib_Tuple(["", ln])); return i; } @@ -1178,7 +1253,7 @@ __SinkParser.prototype.object = function(str, i, res) { else { var i = j; } - if ((str[i] == "\"")) { + if ((str.charAt(i) == "\"")) { if ((pyjslib_slice(str, i, ( i + 3 ) ) == "\"\"\"")) { var delim = "\"\"\""; } @@ -1211,7 +1286,7 @@ __SinkParser.prototype.nodeOrLiteral = function(str, i, res) { else { var i = j; } - var ch = str[i]; + var ch = str.charAt(i); if (("-+0987654321".indexOf(ch) >= 0)) { number_syntax.lastIndex = 0; var m = number_syntax.exec(str.slice(i)); @@ -1221,17 +1296,17 @@ __SinkParser.prototype.nodeOrLiteral = function(str, i, res) { var j = ( i + number_syntax.lastIndex ) ; var val = pyjslib_slice(str, i, j); if ((val.indexOf("e") >= 0)) { - res.push(this._store.literal(parseFloat(val), undefined, kb.sym(FLOAT_DATATYPE))); + res.push(this._store.literal(parseFloat(val), undefined, this._store.sym(FLOAT_DATATYPE))); } else if ((pyjslib_slice(str, i, j).indexOf(".") >= 0)) { - res.push(this._store.literal(parseFloat(val), undefined, kb.sym(DECIMAL_DATATYPE))); + res.push(this._store.literal(parseFloat(val), undefined, this._store.sym(DECIMAL_DATATYPE))); } else { - res.push(this._store.literal(parseInt(val), undefined, kb.sym(INTEGER_DATATYPE))); + res.push(this._store.literal(parseInt(val), undefined, this._store.sym(INTEGER_DATATYPE))); } return j; } - if ((str[i] == "\"")) { + if ((str.charAt(i) == "\"")) { if ((pyjslib_slice(str, i, ( i + 3 ) ) == "\"\"\"")) { var delim = "\"\"\""; } @@ -1283,7 +1358,7 @@ __SinkParser.prototype.strconst = function(str, i, delim) { if ((pyjslib_slice(str, j, i) == delim)) { return new pyjslib_Tuple([i, ustr]); } - if ((str[j] == "\"")) { + if ((str.charAt(j) == "\"")) { var ustr = ( ustr + "\"" ) ; var j = ( j + 1 ) ; continue; @@ -1295,7 +1370,7 @@ __SinkParser.prototype.strconst = function(str, i, delim) { } var i = ( ( j + interesting.lastIndex ) - 1 ) ; var ustr = ( ustr + pyjslib_slice(str, j, i) ) ; - var ch = str[i]; + var ch = str.charAt(i); if ((ch == "\"")) { var j = i; continue; @@ -1322,7 +1397,7 @@ __SinkParser.prototype.strconst = function(str, i, delim) { } var k = string_find("abfrtvn\\\"", ch); if ((k >= 0)) { - var uch = "\a\b\f\r\t\v\n\\\""[k]; + var uch = "\a\b\f\r\t\v\n\\\"".charAt(k); var ustr = ( ustr + uch ) ; var j = ( j + 1 ) ; } @@ -1387,7 +1462,36 @@ __SinkParser.prototype.UEscape = function(str, i, startline) { var uch = stringFromCharCode( ( ( "0x" + pyjslib_slice(value, 2, 10) ) - 0 ) ); return new pyjslib_Tuple([j, uch]); }; - +function OLD_BadSyntax(uri, lines, str, i, why) { + return new __OLD_BadSyntax(uri, lines, str, i, why); +} +function __OLD_BadSyntax(uri, lines, str, i, why) { + this._str = str.encode("utf-8"); + this._str = str; + this._i = i; + this._why = why; + this.lines = lines; + this._uri = uri; +} +__OLD_BadSyntax.prototype.toString = function() { + var str = this._str; + var i = this._i; + var st = 0; + if ((i > 60)) { + var pre = "..."; + var st = ( i - 60 ) ; + } + else { + var pre = ""; + } + if (( ( pyjslib_len(str) - i ) > 60)) { + var post = "..."; + } + else { + var post = ""; + } + return "Line %i of <%s>: Bad syntax (%s) at ^ in:\n\"%s%s^%s%s\"" % new pyjslib_Tuple([ ( this.lines + 1 ) , this._uri, this._why, pre, pyjslib_slice(str, st, i), pyjslib_slice(str, i, ( i + 60 ) ), post]); +}; function BadSyntax(uri, lines, str, i, why) { return ( ( ( ( ( ( ( ( "Line " + ( lines + 1 ) ) + " of <" ) + uri ) + ">: Bad syntax: " ) + why ) + "\nat: \"" ) + pyjslib_slice(str, i, ( i + 30 ) ) ) + "\"" ) ; } @@ -1420,4 +1524,6 @@ function stripCR(str) { function dummyWrite(x) { } +return SinkParser; +}(); diff --git a/chrome/content/zotero/xpcom/rdf/rdfparser.js b/chrome/content/zotero/xpcom/rdf/rdfparser.js @@ -61,7 +61,9 @@ * @constructor * @param {RDFStore} store An RDFStore object */ -function RDFParser(store) { +$rdf.RDFParser = function (store) { + var RDFParser = {}; + /** Standard namespaces that we know how to handle @final * @member RDFParser */ @@ -111,7 +113,7 @@ function RDFParser(store) { /** Add a symbol of a certain type to the this frame */ 'addSymbol': function (type, uri) { - uri = Util.uri.join(uri, this['base']) + uri = $rdf.Util.uri.join(uri, this['base']) this['node'] = this['store']['sym'](uri) this['nodeType'] = type }, @@ -129,7 +131,7 @@ function RDFParser(store) { } if (this['parent']['rdfid'] != null) { // reify var triple = this['store']['sym']( - Util.uri.join("#"+this['parent']['rdfid'], + $rdf.Util.uri.join("#"+this['parent']['rdfid'], this['base'])) this['store']['add'](triple, this['store']['sym']( @@ -236,6 +238,29 @@ function RDFParser(store) { } } + //from the OpenLayers source .. needed to get around IE problems. + this['getAttributeNodeNS'] = function(node, uri, name) { + var attributeNode = null; + if(node.getAttributeNodeNS) { + attributeNode = node.getAttributeNodeNS(uri, name); + } else { + var attributes = node.attributes; + var potentialNode, fullName; + for(var i=0; i<attributes.length; ++i) { + potentialNode = attributes[i]; + if(potentialNode.namespaceURI == uri) { + fullName = (potentialNode.prefix) ? + (potentialNode.prefix + ":" + name) : name; + if(fullName == potentialNode.nodeName) { + attributeNode = potentialNode; + break; + } + } + } + } + return attributeNode; + } + /** Our triple store reference @private */ this['store'] = store /** Our identified blank nodes @private */ @@ -259,8 +284,7 @@ function RDFParser(store) { this['cleanParser']() // figure out the root element - var root = document.documentElement; //this is faster, I think, cross-browser issue? well, DOM 2 - /* + //var root = document.documentElement; //this is faster, I think, cross-browser issue? well, DOM 2 if (document['nodeType'] == RDFParser['nodeType']['DOCUMENT']) { for (var c=0; c<children['length']; c++) { if (children[c]['nodeType'] @@ -278,7 +302,6 @@ function RDFParser(store) { + ". Halting. ") return false } - */ this['why'] = why @@ -296,11 +319,23 @@ function RDFParser(store) { this['parseDOM'] = function (frame) { // a DOM utility function used in parsing var elementURI = function (el) { + var result = ""; if (el['namespaceURI'] == null) { throw new Error("RDF/XML syntax error: No namespace for " +el['localName']+" in "+this.base) } - return el['namespaceURI'] + el['localName'] + if( el['namespaceURI'] ) { + result = result + el['namespaceURI']; + } + if( el['localName'] ) { + result = result + el['localName']; + } else if( el['nodeName'] ) { + if(el['nodeName'].indexOf(":")>=0) + result = result + el['nodeName'].split(":")[1]; + else + result = result + el['nodeName']; + } + return result; } var dig = true // if we'll dig down in the tree on the next iter @@ -325,9 +360,9 @@ function RDFParser(store) { if (!frame['parent'] || !frame['parent']['nodeType'] || frame['parent']['nodeType'] == frame['ARC']) { // we need a node - var about =dom['getAttributeNodeNS']( + var about =this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'],"about") - var rdfid =dom['getAttributeNodeNS']( + var rdfid =this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'],"ID") if (about && rdfid) { throw new Error("RDFParser: " + dom['nodeName'] @@ -341,7 +376,7 @@ function RDFParser(store) { dom['removeAttributeNode'](rdfid) } else if (about == null && rdfid == null) { - var bnid = dom['getAttributeNodeNS']( + var bnid = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'],"nodeID") if (bnid) { frame['addBNode'](bnid['nodeValue']) @@ -354,7 +389,7 @@ function RDFParser(store) { } // Typed nodes - var rdftype = dom['getAttributeNodeNS']( + var rdftype = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'],"type") if (RDFParser['ns']['RDF']+"Description" != elementURI(dom)) { @@ -365,7 +400,7 @@ function RDFParser(store) { this['store']['sym']( RDFParser['ns']['RDF']+"type"), this['store']['sym']( - Util.uri.join( + $rdf.Util.uri.join( rdftype['nodeValue'], frame['base'])), this['why']) @@ -390,7 +425,7 @@ function RDFParser(store) { // save the arc's rdf:ID if it has one if (this['reify']) { - var rdfid = dom['getAttributeNodeNS']( + var rdfid = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'],"ID") if (rdfid) { frame['rdfid'] = rdfid['nodeValue'] @@ -398,9 +433,9 @@ function RDFParser(store) { } } - var parsetype = dom['getAttributeNodeNS']( + var parsetype = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'],"parseType") - var datatype = dom['getAttributeNodeNS']( + var datatype = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'],"datatype") if (datatype) { frame['datatype'] = datatype['nodeValue'] @@ -432,9 +467,9 @@ function RDFParser(store) { } if (attrs['length'] != 0) { - var resource = dom['getAttributeNodeNS']( + var resource = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'],"resource") - var bnid = dom['getAttributeNodeNS']( + var bnid = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'],"nodeID") frame = this['buildFrame'](frame) @@ -549,7 +584,7 @@ function RDFParser(store) { if (attrs[x].name.slice(0,6)=='xmlns:') { var uri = attrs[x].nodeValue; // alert('base for namespac attr:'+this.base); - if (this.base) uri = Util.uri.join(uri, this.base); + if (this.base) uri = $rdf.Util.uri.join(uri, this.base); this.store.setPrefixForURI(attrs[x].name.slice(6), uri); } @@ -559,4 +594,4 @@ function RDFParser(store) { } return frame } -} -\ No newline at end of file +} diff --git a/chrome/content/zotero/xpcom/rdf/serialize.js b/chrome/content/zotero/xpcom/rdf/serialize.js @@ -7,7 +7,11 @@ ** in XML (from mhausenblas) */ -__Serializer = function(){ +// @@@ Check the whole toStr thing tosee whetehr it still makes sense -- tbl +// +$rdf.Serializer = function() { + +var __Serializer = function( store ){ this.flags = ""; this.base = null; this.prefixes = []; @@ -15,11 +19,12 @@ __Serializer = function(){ this.prefixchars = "abcdefghijklmnopqustuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; this.incoming = null; // Array not calculated yet this.formulas = []; // remebering original formulae from hashes + this.store = store; /* pass */ } -Serializer = function() {return new __Serializer()}; +var Serializer = function( store ) {return new __Serializer( store )}; __Serializer.prototype.setBase = function(base) { this.base = base }; @@ -42,7 +47,7 @@ __Serializer.prototype.fromStr = function(s) { if (!x) alert('No formula object for '+s) return x; } - return kb.fromNT(s); + return this.store.fromNT(s); }; @@ -75,11 +80,14 @@ __Serializer.prototype.makeUpPrefix = function(uri) { function canUse(pp) { if (namespaces[pp]) return false; // already used + sz.prefixes[uri] = pp; pok = pp; return true } - for (var ns in sz.prefixes) namespaces[sz.prefixes[ns]] = ns; // reverse index + for (var ns in sz.prefixes) { + namespaces[sz.prefixes[ns]] = ns; // reverse index + } if ('#/'.indexOf(p[p.length-1]) >= 0) p = p.slice(0, -1); var slash = p.lastIndexOf('/'); if (slash >= 0) p = p.slice(slash+1); @@ -97,62 +105,152 @@ __Serializer.prototype.makeUpPrefix = function(uri) { } -/* The scan is to find out which nodes will have to be the roots of trees -** in the serialized form. This will be any symbols, and any bnodes -** which hve more or less than one incoming arc, and any bnodes which have -** one incoming arc but it is an uninterrupted loop of such nodes back to itself. -** This should be kept linear time with repect to the number of statements. -** Note it does not use any indexing. -*/ - // Todo: // - Sort the statements by subject, pred, object // - do stuff about the docu first and then (or first) about its primary topic. __Serializer.prototype.rootSubjects = function(sts) { - var incoming = {}; - var subjects = {}; + var incoming = []; + var subjects = []; var sz = this; + var allBnodes = {}; +/* This scan is to find out which nodes will have to be the roots of trees +** in the serialized form. This will be any symbols, and any bnodes +** which hve more or less than one incoming arc, and any bnodes which have +** one incoming arc but it is an uninterrupted loop of such nodes back to itself. +** This should be kept linear time with repect to the number of statements. +** Note it does not use any indexing of the store. +*/ + + + tabulator.log.debug('serialize.js Find bnodes with only one incoming arc\n') for (var i = 0; i<sts.length; i++) { + var st = sts[i]; + [ st.subject, st.predicate, st.object].map(function(y){ + if (y.termType =='bnode'){allBnodes[y.toNT()] = true}}); var x = sts[i].object; if (!incoming[x]) incoming[x] = []; - incoming[x].push(sts[i].subject) // List of things which will cause this to be printed - var ss = subjects[sz.toStr(sts[i].subject)]; // Statements with this as subject + incoming[x].push(st.subject) // List of things which will cause this to be printed + var ss = subjects[sz.toStr(st.subject)]; // Statements with this as subject if (!ss) ss = []; - ss.push(sts[i]); - subjects[this.toStr(sts[i].subject)] = ss; // Make hash. @@ too slow for formula? - tabulator.log.debug(' sz potential subject: '+sts[i].subject) + ss.push(st); + subjects[this.toStr(st.subject)] = ss; // Make hash. @@ too slow for formula? + //$rdf.log.debug(' sz potential subject: '+sts[i].subject) } var roots = []; - var loopBreakers = {}; - - function accountedFor(x, start) { - if (x.termType != 'bnode') return true; // will be subject - var zz = incoming[x]; - if (!zz || zz.length != 1) return true; - if (loopBreakers[x]) return true; - if (zz[0] == start) return false; - return accountedFor(zz[0], start); - } for (var xNT in subjects) { var x = sz.fromStr(xNT); if ((x.termType != 'bnode') || !incoming[x] || (incoming[x].length != 1)){ roots.push(x); - tabulator.log.debug(' sz actual subject -: ' + x) + //$rdf.log.debug(' sz actual subject -: ' + x) continue; } - if (accountedFor(incoming[x][0]), x) { - continue; + } + this.incoming = incoming; // Keep for serializing @@ Bug for nested formulas + +//////////// New bit for CONNECTED bnode loops:frootshash + +// This scans to see whether the serialization is gpoing to lead to a bnode loop +// and at the same time accumulates a list of all bnodes mentioned. +// This is in fact a cut down N3 serialization +/* + tabulator.log.debug('serialize.js Looking for connected bnode loops\n') + for (var i=0; i<sts.length; i++) { // @@TBL + // dump('\t'+sts[i]+'\n'); + } + var doneBnodesNT = {}; + function dummyPropertyTree(subject, subjects, rootsHash) { + // dump('dummyPropertyTree('+subject+'...)\n'); + var sts = subjects[sz.toStr(subject)]; // relevant statements + for (var i=0; i<sts.length; i++) { + dummyObjectTree(sts[i].object, subjects, rootsHash); + } + } + + // Convert a set of statements into a nested tree of lists and strings + // @param force, "we know this is a root, do it anyway. It isn't a loop." + function dummyObjectTree(obj, subjects, rootsHash, force) { + // dump('dummyObjectTree('+obj+'...)\n'); + if (obj.termType == 'bnode' && (subjects[sz.toStr(obj)] && + (force || (rootsHash[obj.toNT()] == undefined )))) {// and there are statements + if (doneBnodesNT[obj.toNT()]) { // Ah-ha! a loop + throw "Serializer: Should be no loops "+obj; + } + doneBnodesNT[obj.toNT()] = true; + return dummyPropertyTree(obj, subjects, rootsHash); + } + return dummyTermToN3(obj, subjects, rootsHash); + } + + // Scan for bnodes nested inside lists too + function dummyTermToN3(expr, subjects, rootsHash) { + if (expr.termType == 'bnode') doneBnodesNT[expr.toNT()] = true; + tabulator.log.debug('serialize: seen '+expr); + if (expr.termType == 'collection') { + for (i=0; i<expr.elements.length; i++) { + if (expr.elements[i].termType == 'bnode') + dummyObjectTree(expr.elements[i], subjects, rootsHash); + } + return; + } + } + + // The tree for a subject + function dummySubjectTree(subject, subjects, rootsHash) { + // dump('dummySubjectTree('+subject+'...)\n'); + if (subject.termType == 'bnode' && !incoming[subject]) + return dummyObjectTree(subject, subjects, rootsHash, true); // Anonymous bnode subject + dummyTermToN3(subject, subjects, rootsHash); + dummyPropertyTree(subject, subjects, rootsHash); + } +*/ + // Now do the scan using existing roots + tabulator.log.debug('serialize.js Dummy serialize to check for missing nodes') + var rootsHash = {}; + for (var i = 0; i< roots.length; i++) rootsHash[roots[i].toNT()] = true; +/* + for (var i=0; i<roots.length; i++) { + var root = roots[i]; + dummySubjectTree(root, subjects, rootsHash); + } + // dump('Looking for mising bnodes...\n') + +// Now in new roots for anythig not acccounted for +// Now we check for any bndoes which have not been covered. +// Such bnodes must be in isolated rings of pure bnodes. +// They each have incoming link of 1. + + tabulator.log.debug('serialize.js Looking for connected bnode loops\n') + for (;;) { + var bnt; + var found = null; + for (bnt in allBnodes) { // @@ Note: not repeatable. No canonicalisation + if (doneBnodesNT[bnt]) continue; + found = bnt; // Ah-ha! not covered + break; + } + if (found == null) break; // All done - no bnodes left out/ + // dump('Found isolated bnode:'+found+'\n'); + doneBnodesNT[bnt] = true; + var root = this.store.fromNT(found); + roots.push(root); // Add a new root + rootsHash[found] = true; + tabulator.log.debug('isolated bnode:'+found+', subjects[found]:'+subjects[found]+'\n'); + if (subjects[found] == undefined) { + for (var i=0; i<sts.length; i++) { + // dump('\t'+sts[i]+'\n'); + } + throw "Isolated node should be a subject" +found; } - roots.push(x); - tabulator.log.debug(' sz potential subject *: '+sts[i].subject) - loopBreakers[x] = 1; + dummySubjectTree(root, subjects, rootsHash); // trace out the ring } - this.incoming = incoming; // Keep for serializing - return [roots, subjects]; + // dump('Done bnode adjustments.\n') +*/ + return {'roots':roots, 'subjects':subjects, + 'rootsHash': rootsHash, 'incoming': incoming}; } //////////////////////////////////////////////////////// @@ -169,7 +267,6 @@ __Serializer.prototype._notNameChars = __Serializer.prototype.statementsToN3 = function(sts) { var indent = 4; var width = 80; - // var subjects = null; // set later var sz = this; var namespaceCounts = []; // which have been used @@ -253,37 +350,36 @@ __Serializer.prototype.statementsToN3 = function(sts) { ////////////////////////////////////////////// Structure for N3 + // Convert a set of statements into a nested tree of lists and strings function statementListToTree(statements) { // print('Statement tree for '+statements.length); var res = []; - var pair = sz.rootSubjects(statements); - var roots = pair[0]; - // print('Roots: '+roots) - var subjects = pair[1]; + var stats = sz.rootSubjects(statements); + var roots = stats.roots; var results = [] for (var i=0; i<roots.length; i++) { var root = roots[i]; - results.push(subjectTree(root, subjects)) + results.push(subjectTree(root, stats)) } return results; } // The tree for a subject - function subjectTree(subject, subjects) { - if (subject.termType == 'bnode' && !sz.incoming[subject]) - return objectTree(subject, subjects).concat(["."]); // Anonymous bnode subject - return [ termToN3(subject, subjects) ].concat([propertyTree(subject, subjects)]).concat(["."]); + function subjectTree(subject, stats) { + if (subject.termType == 'bnode' && !stats.incoming[subject]) + return objectTree(subject, stats, true).concat(["."]); // Anonymous bnode subject + return [ termToN3(subject, stats) ].concat([propertyTree(subject, stats)]).concat(["."]); } // The property tree for a single subject or anonymous node - function propertyTree(subject, subjects) { + function propertyTree(subject, stats) { // print('Proprty tree for '+subject); var results = [] var lastPred = null; - var sts = subjects[sz.toStr(subject)]; // relevant statements + var sts = stats.subjects[sz.toStr(subject)]; // relevant statements if (typeof sts == 'undefined') { - alert('Cant find statements for '+subject); + throw('Cant find statements for '+subject); } sts.sort(); var objects = []; @@ -297,34 +393,31 @@ __Serializer.prototype.statementsToN3 = function(sts) { objects = []; } results.push(predMap[st.predicate.uri] ? - predMap[st.predicate.uri] : termToN3(st.predicate, subjects)); + predMap[st.predicate.uri] : termToN3(st.predicate, stats)); } lastPred = st.predicate.uri; - objects.push(objectTree(st.object, subjects)); + objects.push(objectTree(st.object, stats)); } results=results.concat([objects]); return results; } - // Convert a set of statements into a nested tree of lists and strings - function objectTree(obj, subjects) { - if (obj.termType == 'bnode' && subjects[sz.toStr(obj)]) // and there are statements - return ['['].concat(propertyTree(obj, subjects)).concat([']']); - return termToN3(obj, subjects); + function objectTree(obj, stats, force) { + if (obj.termType == 'bnode' && + stats.subjects[sz.toStr(obj)] && // and there are statements + (force || stats.rootsHash[obj.toNT()] == undefined)) // and not a root + return ['['].concat(propertyTree(obj, stats)).concat([']']); + return termToN3(obj, stats); } - ////////////////////////////////////////////// Atomic Terms - - // Deal with term level things and nesting with no bnode structure - - function termToN3(expr, subjects) { + function termToN3(expr, stats) { switch(expr.termType) { case 'bnode': case 'variable': return expr.toNT(); case 'literal': var str = stringToN3(expr.value); if (expr.lang) str+= '@' + expr.lang; - if (expr.dt) str+= '^^' + termToN3(expr.dt, subjects); + if (expr.datatype) str+= '^^' + termToN3(expr.datatype, stats); return str; case 'symbol': return symbolToN3(expr.uri); @@ -335,7 +428,7 @@ __Serializer.prototype.statementsToN3 = function(sts) { case 'collection': var res = ['(']; for (i=0; i<expr.elements.length; i++) { - res.push( [ objectTree(expr.elements[i], subjects) ]); + res.push( [ objectTree(expr.elements[i], stats) ]); } res.push(')'); return res; @@ -346,6 +439,10 @@ __Serializer.prototype.statementsToN3 = function(sts) { } } + ////////////////////////////////////////////// Atomic Terms + + // Deal with term level things and nesting with no bnode structure + function symbolToN3(uri) { // c.f. symbolString() in notation3.py var j = uri.indexOf('#'); if (j<0 && sz.flags.indexOf('/') < 0) { @@ -379,7 +476,7 @@ __Serializer.prototype.statementsToN3 = function(sts) { } } if (sz.flags.indexOf('r') < 0 && sz.base) - uri = Util.uri.refTo(sz.base, uri); + uri = $rdf.Util.uri.refTo(sz.base, uri); else if (sz.flags.indexOf('u') >= 0) uri = backslashUify(uri); else uri = hexify(uri); @@ -489,7 +586,6 @@ function backslashUify(str) { __Serializer.prototype.statementsToXML = function(sts) { var indent = 4; var width = 80; - // var subjects = null; // set later var sz = this; var namespaceCounts = []; // which have been used @@ -552,137 +648,90 @@ __Serializer.prototype.statementsToXML = function(sts) { function statementListToXMLTree(statements) { sz.suggestPrefix('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'); - var res = []; - var pair = sz.rootSubjects(statements); - var roots = pair[0]; - var subjects = pair[1]; + var stats = sz.rootSubjects(statements); + var roots = stats.roots; results = [] for (var i=0; i<roots.length; i++) { root = roots[i]; - results.push(subjectXMLTree(root, subjects)) + results.push(subjectXMLTree(root, stats)) } return results; } function escapeForXML(str) { if (typeof str == 'undefined') return '@@@undefined@@@@'; - return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;'); + return str.replace(/&/g, '&amp;').replace(/</g, '&lt;') } function relURI(term) { - return escapeForXML((sz.base) ? Util.uri.refTo(this.base, term.uri) : term.uri); + return escapeForXML((sz.base) ? $rdf.Util.uri.refTo(this.base, term.uri) : term.uri); } // The tree for a subject - function subjectXMLTree(subject, subjects, referenced) { - const liPrefix = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#_'; - - var type = null; - - var results = [] - var sts = subjects[sz.toStr(subject)]; // relevant statements - // Sort only on the predicate, leave the order at object - // level undisturbed. This leaves multilingual content in - // the order of entry (for partner literals), which helps - // readability. - // - // For the predicate sort, we attempt to split the uri - // as a hint to the sequence, as sequenced items seems - // to be of the form http://example.com#_1, http://example.com#_2, - // et cetera. Probably not the most optimal of fixes, but - // it does work. - sts.sort(function(a,b){ - var aa = a.predicate.uri.split('#_'); - var bb = a.predicate.uri.split('#_'); - if (aa[0] > bb[0]) { - return 1; - } else if (aa[0] < bb[0]) { - return -1; - } else { - if ("undefined" !== typeof aa[1] && "undefined" !== typeof bb[1]) { - if (parseInt(aa[1], 10) > parseInt(bb[1], 10)) { - return 1; - } else if (parseInt(aa[1], 10) < parseInt(bb[1], 10)) { - return -1; - } - } - } - return 0; - }); - for (var i=0; i<sts.length; i++) { - var st = sts[i]; - - if(st.predicate.uri == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' && !type && st.object.termType == "symbol") { - // look for a type - type = st.object; - } else { - // see whether predicate can be replaced with "li" - if(st.predicate.uri.substr(0, liPrefix.length) == liPrefix) { - var number = st.predicate.uri.substr(liPrefix.length); - - // make sure these are actually numeric list items - var intNumber = parseInt(number); - if(number == intNumber.toString()) { - // was numeric; don't need to worry about ordering since we've already - // sorted the statements - st.predicate = RDFSymbol('http://www.w3.org/1999/02/22-rdf-syntax-ns#li'); - } - } - - switch (st.object.termType) { - case 'bnode': - if(sz.incoming[st.object].length == 1) { - results = results.concat(['<'+qname(st.predicate)+'>', - subjectXMLTree(st.object, subjects, true), - '</'+qname(st.predicate)+'>']); - } else { - results = results.concat(['<'+qname(st.predicate)+' rdf:nodeID="' - +st.object.toNT().slice(2)+'"/>']); - } - break; - case 'symbol': - results = results.concat(['<'+qname(st.predicate)+' rdf:resource="' - + relURI(st.object)+'"/>']); - break; - case 'literal': - results = results.concat(['<'+qname(st.predicate) - + (st.object.dt ? ' rdf:datatype="'+escapeForXML(st.object.dt.uri)+'"' : '') - + (st.object.lang ? ' xml:lang="'+st.object.lang+'"' : '') - + '>' + escapeForXML(st.object.value) - + '</'+qname(st.predicate)+'>']); - break; - case 'collection': - results = results.concat(['<'+qname(st.predicate)+' rdf:parseType="Collection">', - collectionXMLTree(st.object, subjects), - '</'+qname(st.predicate)+'>']); - break; - default: - throw "Can't serialize object of type "+st.object.termType +" into XML"; - - } // switch - } - } - - var tag = type ? qname(type) : 'rdf:Description'; - - attrs = ''; + function subjectXMLTree(subject, stats) { + var start if (subject.termType == 'bnode') { - if(!referenced || sz.incoming[subject].length != 1) { // not an anonymous bnode - attrs = ' rdf:nodeID="'+subject.toNT().slice(2)+'"'; + if (!stats.incoming[subject]) { // anonymous bnode + var start = '<rdf:Description>'; + } else { + var start = '<rdf:Description rdf:nodeID="'+subject.toNT().slice(2)+'">'; } } else { - attrs = ' rdf:about="'+ relURI(subject)+'"'; + var start = '<rdf:Description rdf:about="'+ relURI(subject)+'">'; } - return [ '<' + tag + attrs + '>' ].concat([results]).concat(["</"+ tag +">"]); + return [ start ].concat( + [propertyXMLTree(subject, stats)]).concat(["</rdf:Description>"]); } - - function collectionXMLTree(subject, subjects) { + function collectionXMLTree(subject, stats) { res = [] for (var i=0; i< subject.elements.length; i++) { - res.push(subjectXMLTree(subject.elements[i], subjects)); + res.push(subjectXMLTree(subject.elements[i], stats)); } return res; + } + + // The property tree for a single subject or anonymos node + function propertyXMLTree(subject, stats) { + var results = [] + var sts = stats.subjects[sz.toStr(subject)]; // relevant statements + if (sts == undefined) return results; // No relevant statements + sts.sort(); + for (var i=0; i<sts.length; i++) { + var st = sts[i]; + switch (st.object.termType) { + case 'bnode': + if(stats.rootsHash[st.object.toNT()]) { // This bnode has been done as a root -- no content here @@ what bout first time + results = results.concat(['<'+qname(st.predicate)+' rdf:nodeID="'+st.object.toNT().slice(2)+'">', + '</'+qname(st.predicate)+'>']); + } else { + results = results.concat(['<'+qname(st.predicate)+' rdf:parseType="Resource">', + propertyXMLTree(st.object, stats), + '</'+qname(st.predicate)+'>']); + } + break; + case 'symbol': + results = results.concat(['<'+qname(st.predicate)+' rdf:resource="' + + relURI(st.object)+'"/>']); + break; + case 'literal': + results = results.concat(['<'+qname(st.predicate) + + (st.object.datatype ? ' rdf:datatype="'+escapeForXML(st.object.datatype.uri)+'"' : '') + + (st.object.lang ? ' xml:lang="'+st.object.lang+'"' : '') + + '>' + escapeForXML(st.object.value) + + '</'+qname(st.predicate)+'>']); + break; + case 'collection': + results = results.concat(['<'+qname(st.predicate)+' rdf:parseType="Collection">', + collectionXMLTree(st.object, stats), + '</'+qname(st.predicate)+'>']); + break; + default: + throw "Can't serialize object of type "+st.object.termType +" into XML"; + + } // switch + } + return results; } function qname(term) { @@ -730,3 +779,7 @@ __Serializer.prototype.statementsToXML = function(sts) { } // End @@ body +return Serializer; + +}(); + diff --git a/chrome/content/zotero/xpcom/rdf/term.js b/chrome/content/zotero/xpcom/rdf/term.js @@ -8,224 +8,245 @@ // W3C open source licence 2005. // -RDFTracking = 0 // Are we requiring reasons for statements? - -//takes in an object and makes it an object if it's a literal -function makeTerm(val) { - // tabulator.log.debug("Making term from " + val) - if (typeof val == 'object') return val; - if (typeof val == 'string') return new RDFLiteral(val); - if (typeof val == 'number') return new RDFLiteral(val); // @@ differet types - if (typeof val == 'boolean') return new RDFLiteral(val?"1":"0", undefined, - RDFSymbol.prototype.XSDboolean); - if (typeof val == 'undefined') return undefined; - alert("Can't make term from " + val + " of type " + typeof val); -} - - // Symbol -function RDFEmpty() { +$rdf.Empty = function() { return this; -} -RDFEmpty.prototype.termType = 'empty' -RDFEmpty.prototype.toString = function () { return "()" } -RDFEmpty.prototype.toNT = function () { return "@@" } - -function RDFSymbol_toNT(x) { - return ("<" + x.uri + ">") -} +}; -function toNT() { - return RDFSymbol_toNT(this) -} +$rdf.Empty.prototype.termType = 'empty'; +$rdf.Empty.prototype.toString = function () { return "()" }; +$rdf.Empty.prototype.toNT = $rdf.Empty.prototype.toString; -function RDFSymbol(uri) { - this.uri = uri - return this +$rdf.Symbol = function( uri ) { + this.uri = uri; + this.value = uri; // -- why? -tim + return this; } - -RDFSymbol.prototype.termType = 'symbol' -RDFSymbol.prototype.toString = toNT -RDFSymbol.prototype.toNT = toNT -// Some precalculaued symbols - -RDFSymbol.prototype.XSDboolean = new RDFSymbol('http://www.w3.org/2001/XMLSchema#boolean'); -RDFSymbol.prototype.integer = new RDFSymbol('http://www.w3.org/2001/XMLSchema#integer'); +$rdf.Symbol.prototype.termType = 'symbol'; +$rdf.Symbol.prototype.toString = function () { return ("<" + this.uri + ">"); }; +$rdf.Symbol.prototype.toNT = $rdf.Symbol.prototype.toString; +// Some precalculated symbols +$rdf.Symbol.prototype.XSDboolean = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#boolean'); +$rdf.Symbol.prototype.XSDdecimal = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#decimal'); +$rdf.Symbol.prototype.XSDfloat = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#float'); +$rdf.Symbol.prototype.XSDinteger = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#integer'); +$rdf.Symbol.prototype.XSDdateTime = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#dateTime'); +$rdf.Symbol.prototype.integer = new $rdf.Symbol('http://www.w3.org/2001/XMLSchema#integer'); // Used? // Blank Node -var RDFNextId = 0; // Gobal genid -RDFGenidPrefix = "genid:" -NTAnonymousNodePrefix = "_:n" +if (typeof $rdf.NextId != 'undefined') { + $rdf.log.error('Attempt to re-zero existing blank node id counter at '+$rdf.NextId); +} else { + $rdf.NextId = 0; // Global genid +} +$rdf.NTAnonymousNodePrefix = "_:n"; -function RDFBlankNode(id) { +$rdf.BlankNode = function ( id ) { /*if (id) this.id = id; else*/ - this.id = RDFNextId++ + this.id = $rdf.NextId++ + this.value = id ? id : this.id.toString(); return this -} - -RDFBlankNode.prototype.termType = 'bnode' +}; -RDFBlankNode.prototype.toNT = function() { - return NTAnonymousNodePrefix + this.id -} -RDFBlankNode.prototype.toString = RDFBlankNode.prototype.toNT +$rdf.BlankNode.prototype.termType = 'bnode'; +$rdf.BlankNode.prototype.toNT = function() { + return $rdf.NTAnonymousNodePrefix + this.id +}; +$rdf.BlankNode.prototype.toString = $rdf.BlankNode.prototype.toNT; // Literal -function RDFLiteral(value, lang, datatype) { +$rdf.Literal = function (value, lang, datatype) { this.value = value - this.lang=lang; // string - this.datatype=datatype; // term - this.toString = RDFLiteralToString - this.toNT = RDFLiteral_toNT - return this + if (lang == "" || lang == null) this.lang = undefined; + else this.lang = lang; // string + if (datatype == null) this.datatype = undefined; + else this.datatype = datatype; // term + return this; } -RDFLiteral.prototype.termType = 'literal' - -function RDFLiteral_toNT() { +$rdf.Literal.prototype.termType = 'literal' +$rdf.Literal.prototype.toString = function() { + return ''+this.value; +}; +$rdf.Literal.prototype.toNT = function() { var str = this.value if (typeof str != 'string') { if (typeof str == 'number') return ''+str; throw Error("Value of RDF literal is not string: "+str) } - str = str.replace(/\\/g, '\\\\'); // escape - str = str.replace(/\"/g, '\\"'); - str = '"' + str + '"' //' + str = str.replace(/\\/g, '\\\\'); // escape backslashes + str = str.replace(/\"/g, '\\"'); // escape quotes + str = str.replace(/\n/g, '\\n'); // escape newlines + str = '"' + str + '"' //'; if (this.datatype){ - str = str + '^^' + this.datatype//.toNT() + str = str + '^^' + this.datatype.toNT() } if (this.lang) { - str = str + "@" + this.lang + str = str + "@" + this.lang; } - return str -} + return str; +}; -function RDFLiteralToString() { - return ''+this.value -} - -RDFLiteral.prototype.toString = RDFLiteralToString -RDFLiteral.prototype.toNT = RDFLiteral_toNT +$rdf.Collection = function() { + this.id = $rdf.NextId++; // Why need an id? For hashstring. + this.elements = []; + this.closed = false; +}; -function RDFCollection() { - this.id = RDFNextId++ - this.elements = [] - this.closed = false -} +$rdf.Collection.prototype.termType = 'collection'; -RDFCollection.prototype.termType = 'collection' +$rdf.Collection.prototype.toNT = function() { + return $rdf.NTAnonymousNodePrefix + this.id +}; -RDFCollection.prototype.toNT = function() { - return NTAnonymousNodePrefix + this.id -} -RDFCollection.prototype.toString = RDFCollection.prototype.toNT +$rdf.Collection.prototype.toString = function() { + var str='('; + for (var i=0; i<this.elements.length; i++) + str+= this.elements[i] + ' '; + return str + ')'; +}; -RDFCollection.prototype.append = function (el) { +$rdf.Collection.prototype.append = function (el) { this.elements.push(el) } -RDFCollection.prototype.unshift=function(el){ +$rdf.Collection.prototype.unshift=function(el){ this.elements.unshift(el); } -RDFCollection.prototype.shift=function(){ +$rdf.Collection.prototype.shift=function(){ return this.elements.shift(); } -RDFCollection.prototype.close = function () { +$rdf.Collection.prototype.close = function () { this.closed = true } + +// Convert Javascript representation to RDF term object +// +$rdf.term = function(val) { + if (typeof val == 'object') + if (val instanceof Date) { + var d2=function(x) {return(''+(100+x)).slice(1,3)}; // format as just two digits + return new $rdf.Literal( + ''+ val.getUTCFullYear() + '-'+ + d2(val.getUTCMonth()+1) +'-'+d2(val.getUTCDate())+ + 'T'+d2(val.getUTCHours())+':'+d2(val.getUTCMinutes())+ + ':'+d2(val.getUTCSeconds())+'Z', + undefined, $rdf.Symbol.prototype.XSDdateTime); + + } + else if (val instanceof Array) { + var x = new $rdf.Collection(); + for (var i=0; i<val.length; i++) x.append($rdf.term(val[i])); + return x; + } + else return val; + if (typeof val == 'string') return new $rdf.Literal(val); + if (typeof val == 'number') { + var dt; + if ((''+val).indexOf('e')>=0) dt = $rdf.Symbol.prototype.XSDfloat; + else if ((''+val).indexOf('.')>=0) dt = $rdf.Symbol.prototype.XSDdecimal; + else dt = $rdf.Symbol.prototype.XSDinteger; + return new $rdf.Literal(val, undefined, dt); + } + if (typeof val == 'boolean') return new $rdf.Literal(val?"1":"0", undefined, + $rdf.Symbol.prototype.XSDboolean); + if (typeof val == 'undefined') return undefined; + throw ("Can't make term from " + val + " of type " + typeof val); +} + // Statement // // This is a triple with an optional reason. // // The reason can point to provenece or inference // -function RDFStatement_toNT() { - return (this.subject.toNT() + " " - + this.predicate.toNT() + " " - + this.object.toNT() +" .") -} -function RDFStatement(subject, predicate, object, why) { - this.subject = makeTerm(subject) - this.predicate = makeTerm(predicate) - this.object = makeTerm(object) +$rdf.Statement = function(subject, predicate, object, why) { + this.subject = $rdf.term(subject) + this.predicate = $rdf.term(predicate) + this.object = $rdf.term(object) if (typeof why !='undefined') { - this.why = why - } else if (RDFTracking) { - tabulator.log.debug("WARNING: No reason on "+subject+" "+predicate+" "+object) + this.why = why; } - return this + return this; } -RDFStatement.prototype.toNT = RDFStatement_toNT -RDFStatement.prototype.toString = RDFStatement_toNT - +$rdf.st= function(subject, predicate, object, why) { + return new $rdf.Statement(subject, predicate, object, why); +}; + +$rdf.Statement.prototype.toNT = function() { + return (this.subject.toNT() + " " + + this.predicate.toNT() + " " + + this.object.toNT() +" ."); +}; + +$rdf.Statement.prototype.toString = $rdf.Statement.prototype.toNT; // Formula // // Set of statements. -function RDFFormula() { +$rdf.Formula = function() { this.statements = [] this.constraints = [] this.initBindings = [] this.optional = [] - this.superFormula = null; - return this -} + return this; +}; -function RDFFormula_toNT() { - // throw 'Who called me?'; - return "{" + this.statements.join('\n') + "}" -} -//RDFQueryFormula.prototype = new RDFFormula() -//RDFQueryFormula.termType = 'queryFormula' -RDFFormula.prototype.termType = 'formula' -RDFFormula.prototype.toNT = RDFFormula_toNT -RDFFormula.prototype.toString = RDFFormula_toNT +$rdf.Formula.prototype.termType = 'formula'; +$rdf.Formula.prototype.toNT = function() { + return "{" + this.statements.join('\n') + "}" +}; +$rdf.Formula.prototype.toString = $rdf.Formula.prototype.toNT; -RDFFormula.prototype.add = function(subj, pred, obj, why) { - this.statements.push(new RDFStatement(subj, pred, obj, why)) +$rdf.Formula.prototype.add = function(subj, pred, obj, why) { + this.statements.push(new $rdf.Statement(subj, pred, obj, why)) } // Convenience methods on a formula allow the creation of new RDF terms: -RDFFormula.prototype.sym = function(uri,name) { +$rdf.Formula.prototype.sym = function(uri,name) { if (name != null) { - if (!tabulator.ns[uri]) throw 'The prefix "'+uri+'" is not set in the API'; - uri = tabulator.ns[uri] + name + throw "This feature (kb.sym with 2 args) is removed. Do not assume prefix mappings." + if (!$rdf.ns[uri]) throw 'The prefix "'+uri+'" is not set in the API'; + uri = $rdf.ns[uri] + name } - return new RDFSymbol(uri) + return new $rdf.Symbol(uri) } -RDFFormula.prototype.literal = function(val, lang, dt) { - return new RDFLiteral(val.toString(), lang, dt) +$rdf.sym = function(uri) { return new $rdf.Symbol(uri); }; + +$rdf.Formula.prototype.literal = function(val, lang, dt) { + return new $rdf.Literal(val.toString(), lang, dt) } +$rdf.lit = $rdf.Formula.prototype.literal; -RDFFormula.prototype.bnode = function(id) { - return new RDFBlankNode(id) +$rdf.Formula.prototype.bnode = function(id) { + return new $rdf.BlankNode(id) } -RDFFormula.prototype.formula = function() { - return new RDFFormula() +$rdf.Formula.prototype.formula = function() { + return new $rdf.Formula() } -RDFFormula.prototype.collection = function () { // obsolete - return new RDFCollection() +$rdf.Formula.prototype.collection = function () { // obsolete + return new $rdf.Collection() } -RDFFormula.prototype.list = function (values) { - li = new RDFCollection(); +$rdf.Formula.prototype.list = function (values) { + li = new $rdf.Collection(); if (values) { for(var i = 0; i<values.length; i++) { li.append(values[i]); @@ -234,58 +255,46 @@ RDFFormula.prototype.list = function (values) { return li; } -RDFFormula.instances={}; -RDFFormula.prototype.registerFormula = function(accesskey){ - var superFormula = this.superFormula || this; - RDFFormula.instances[accesskey] = this; - var formulaTerm = superFormula.bnode(); - superFormula.add(formulaTerm, tabulator.ns.rdf('type'),superFormula.sym("http://www.w3.org/2000/10/swap/log#Formula")); - superFormula.add(formulaTerm, tabulator.ns.foaf('name'), superFormula.literal(accesskey)); - superFormula.add(formulaTerm, tabulator.ns.link('accesskey'), superFormula.literal(accesskey)); - //RDFFormula.instances.push("accesskey"); -} - - /* Variable ** ** Variables are placeholders used in patterns to be matched. ** In cwm they are symbols which are the formula's list of quantified variables. ** In sparl they are not visibily URIs. Here we compromise, by having -** a common special base URI for variables. +** a common special base URI for variables. Their names are uris, +** but the ? nottaion has an implicit base uri of 'varid:' */ -RDFVariableBase = "varid:"; // We deem variabe x to be the symbol varid:x - -function RDFVariable(rel) { - this.uri = URIjoin(rel, RDFVariableBase); +$rdf.Variable = function(rel) { + this.base = "varid:"; // We deem variabe x to be the symbol varid:x + this.uri = $rdf.Util.uri.join(rel, this.base); return this; } -RDFVariable.prototype.termType = 'variable'; -RDFVariable.prototype.toNT = function() { - if (this.uri.slice(0, RDFVariableBase.length) == RDFVariableBase) { - return '?'+ this.uri.slice(RDFVariableBase.length);} // @@ poor man's refTo +$rdf.Variable.prototype.termType = 'variable'; +$rdf.Variable.prototype.toNT = function() { + if (this.uri.slice(0, this.base.length) == this.base) { + return '?'+ this.uri.slice(this.base.length);} // @@ poor man's refTo return '?' + this.uri; }; -RDFVariable.prototype.toString = RDFVariable.prototype.toNT; -RDFVariable.prototype.classOrder = 7; +$rdf.Variable.prototype.toString = $rdf.Variable.prototype.toNT; +$rdf.Variable.prototype.classOrder = 7; -RDFFormula.prototype.variable = function(name) { - return new RDFVariable(name); +$rdf.variable = $rdf.Formula.prototype.variable = function(name) { + return new $rdf.Variable(name); }; -RDFVariable.prototype.hashString = RDFVariable.prototype.toNT; +$rdf.Variable.prototype.hashString = $rdf.Variable.prototype.toNT; // The namespace function generator -function RDFNamespace(nsuri) { - return function(ln) { return new RDFSymbol(nsuri+(ln===undefined?'':ln)) } +$rdf.Namespace = function (nsuri) { + return function(ln) { return new $rdf.Symbol(nsuri+(ln===undefined?'':ln)) } } -RDFFormula.prototype.ns = function(nsuri) { - return function(ln) { return new RDFSymbol(nsuri+(ln===undefined?'':ln)) } +$rdf.Formula.prototype.ns = function(nsuri) { + return function(ln) { return new $rdf.Symbol(nsuri+(ln===undefined?'':ln)) } } @@ -293,21 +302,44 @@ RDFFormula.prototype.ns = function(nsuri) { // // The bnode bit should not be used on program-external values; designed // for internal work such as storing a bnode id in an HTML attribute. -// Not coded for literals. +// This will only parse the strings generated by the vaious toNT() methods. -RDFFormula.prototype.fromNT = function(str) { +$rdf.Formula.prototype.fromNT = function(str) { var len = str.length var ch = str.slice(0,1) - if (ch == '<') return this.sym(str.slice(1,len-1)) + if (ch == '<') return $rdf.sym(str.slice(1,len-1)) + if (ch == '"') { + var lang = undefined; + var dt = undefined; + var k = str.lastIndexOf('"'); + if (k < len-1) { + if (str[k+1] == '@') lang = str.slice(k+2,len); + else if (str.slice(k+1,k+3) == '^^') dt = $rdf.fromNT(str.slice(k+3,len)); + else throw "Can't convert string from NT: "+str + } + var str = (str.slice(1,k)); + str = str.replace(/\\"/g, '"'); // unescape quotes ' + str = str.replace(/\\n/g, '\n'); // unescape newlines + str = str.replace(/\\\\/g, '\\'); // unescape backslashes + return $rdf.lit(str, lang, dt); + } if (ch == '_') { - var x = new RDFBlankNode(); + var x = new $rdf.BlankNode(); x.id = parseInt(str.slice(3)); - RDFNextId-- + $rdf.NextId-- return x } - throw "Can't convert from NT"+str; + if (ch == '?') { + var x = new $rdf.Variable(str.slice(1)); + return x; + } + throw "Can't convert from NT: "+str; - //alert("Can't yet convert from NT: '"+str+"', "+str[0]) } +$rdf.fromNT = $rdf.Formula.prototype.fromNT; // Not for inexpert user + +// Convenience - and more conventional name: + +$rdf.graph = function(){return new $rdf.IndexedFormula();}; // ends diff --git a/chrome/content/zotero/xpcom/rdf/uri.js b/chrome/content/zotero/xpcom/rdf/uri.js @@ -12,11 +12,10 @@ // See also http://www.w3.org/2000/10/swap/uripath.py // -if (typeof Util == "undefined") { Util = {}} -if (typeof Util.uri == "undefined") { Util.uri = {}} +if (typeof $rdf.Util.uri == "undefined") { $rdf.Util.uri = {}; }; -Util.uri.join = function (given, base) { - // if (typeof tabulator.log.debug != 'undefined') tabulator.log.debug(" URI given="+given+" base="+base) +$rdf.Util.uri.join = function (given, base) { + // if (typeof $rdf.log.debug != 'undefined') $rdf.log.debug(" URI given="+given+" base="+base) var baseHash = base.indexOf('#') if (baseHash > 0) base = base.slice(0, baseHash) if (given.length==0) return base // before chopping its filename off @@ -64,35 +63,38 @@ Util.uri.join = function (given, base) { path = path + given while (path.match(/[^\/]*\/\.\.\//)) // must apply to result of prev path = path.replace( /[^\/]*\/\.\.\//, '') // ECMAscript spec 7.8.5 - path = path.replace( /\.\//g, '') // spec vague on escaping + path = path.replace( /\.\//g, '') // spec vague on escaping path = path.replace( /\/\.$/, '/' ) return base.slice(0, baseSingle) + path } -var tIOService; -if (typeof( isExtension ) != "undefined" && isExtension) { - tIOService = Components.classes['@mozilla.org/network/io-service;1'] +if (typeof tabulator != 'undefined' && tabulator.isExtension) { + $rdf.Util.uri.join2 = function (given, base){ + var tIOService = Components.classes['@mozilla.org/network/io-service;1'] .getService(Components.interfaces.nsIIOService); - Util.uri.join2 = function (given, base){ - var baseURI = tIOService.newURI(base, null, null); - return tIOService.newURI(baseURI.resolve(given), null, null).spec; + + var baseURI = tIOService.newURI(base, null, null); + return tIOService.newURI(baseURI.resolve(given), null, null).spec; } } else - Util.uri.join2 = Util.uri.join; + $rdf.Util.uri.join2 = $rdf.Util.uri.join; // refTo: Make a URI relative to a given base // // based on code in http://www.w3.org/2000/10/swap/uripath.py // -Util.uri.commonHost = new RegExp("^[-_a-zA-Z0-9.]+:(//[^/]*)?/[^/]*$"); -Util.uri.refTo = function(base, uri) { +$rdf.Util.uri.commonHost = new RegExp("^[-_a-zA-Z0-9.]+:(//[^/]*)?/[^/]*$"); + +$rdf.Util.uri.hostpart = function(u) { var m = /[^\/]*\/\/([^\/]*)\//.exec(u); return m? m[1]: '' }; + +$rdf.Util.uri.refTo = function(base, uri) { if (!base) return uri; if (base == uri) return ""; var i =0; // How much are they identical? while (i<uri.length && i < base.length) if (uri[i] == base[i]) i++; else break; - if (base.slice(0,i).match(Util.uri.commonHost)) { + if (base.slice(0,i).match($rdf.Util.uri.commonHost)) { var k = uri.indexOf('//'); if (k<0) k=-2; // no host var l = uri.indexOf('/', k+2); // First *single* slash @@ -119,15 +121,20 @@ Util.uri.refTo = function(base, uri) { /** returns URI without the frag **/ -Util.uri.docpart = function (uri) { +$rdf.Util.uri.docpart = function (uri) { var i = uri.indexOf("#") if (i < 0) return uri return uri.slice(0,i) } +/** The document in which something a thing defined **/ +$rdf.Util.uri.document = function (x) { + return $rdf.sym($rdf.Util.uri.docpart(x.uri)); +} + /** return the protocol of a uri **/ /** return null if there isn't one **/ -Util.uri.protocol = function (uri) { +$rdf.Util.uri.protocol = function (uri) { var index = uri.indexOf(':'); if (index >= 0) return uri.slice(0, index); @@ -135,9 +142,4 @@ Util.uri.protocol = function (uri) { return null; } //protocol -URIjoin = Util.uri.join -uri_docpart = Util.uri.docpart -uri_protocol = Util.uri.protocol - - //ends