diff --git a/chrome/content/zotero/xpcom/rdf/identity.js b/chrome/content/zotero/xpcom/rdf/identity.js index d53b1bcc7..da3b3ead2 100644 --- 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 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) { ''] = [ handleRDFType ]; // Assumption: these terms are not redirected @@fixme - if (features.indexOf("sameAs") >=0) + if ($rdf.Util.ArrayIndexOf(features,"sameAs") >= 0) this.propertyActions[''] = [ 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= 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 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 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; + 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; + } } - 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))) { + 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 index 7a28e7f32..8ab32a545 100644 --- 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=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 index ab0b4648d..3e724a981 100644 --- 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= 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 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', - subjectXMLTree(st.object, subjects, true), - '']); - } 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) - + '']); - break; - case 'collection': - results = results.concat(['<'+qname(st.predicate)+' rdf:parseType="Collection">', - collectionXMLTree(st.object, subjects), - '']); - 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 = ''; + } else { + var start = ''; } } else { - attrs = ' rdf:about="'+ relURI(subject)+'"'; + var start = ''; } - return [ '<' + tag + attrs + '>' ].concat([results]).concat([""]); + return [ start ].concat( + [propertyXMLTree(subject, stats)]).concat([""]); } - - 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', + '']); + } else { + results = results.concat(['<'+qname(st.predicate)+' rdf:parseType="Resource">', + propertyXMLTree(st.object, stats), + '']); + } + 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) + + '']); + break; + case 'collection': + results = results.concat(['<'+qname(st.predicate)+' rdf:parseType="Collection">', + collectionXMLTree(st.object, stats), + '']); + 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 index 0764833da..cced406dd 100644 --- 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 + ">") +$rdf.Empty.prototype.termType = 'empty'; +$rdf.Empty.prototype.toString = function () { return "()" }; +$rdf.Empty.prototype.toNT = $rdf.Empty.prototype.toString; + +$rdf.Symbol = function( uri ) { + this.uri = uri; + this.value = uri; // -- why? -tim + return this; } -function toNT() { - return RDFSymbol_toNT(this) -} - -function RDFSymbol(uri) { - this.uri = uri - 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=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?'; + +$rdf.Formula.prototype.termType = 'formula'; +$rdf.Formula.prototype.toNT = function() { return "{" + this.statements.join('\n') + "}" -} +}; +$rdf.Formula.prototype.toString = $rdf.Formula.prototype.toNT; -//RDFQueryFormula.prototype = new RDFFormula() -//RDFQueryFormula.termType = 'queryFormula' -RDFFormula.prototype.termType = 'formula' -RDFFormula.prototype.toNT = RDFFormula_toNT -RDFFormula.prototype.toString = RDFFormula_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; + +$rdf.Formula.prototype.bnode = function(id) { + return new $rdf.BlankNode(id) } -RDFFormula.prototype.bnode = function(id) { - return new RDFBlankNode(id) +$rdf.Formula.prototype.formula = function() { + return new $rdf.Formula() } -RDFFormula.prototype.formula = function() { - return new RDFFormula() +$rdf.Formula.prototype.collection = function () { // obsolete + return new $rdf.Collection() } -RDFFormula.prototype.collection = function () { // obsolete - return new RDFCollection() -} - -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= 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