Merge pull request #103 from aurimasv/tabulator

Tabulator v0.8 RDF Parser
This commit is contained in:
Simon Kornblith 2012-05-05 12:35:24 -07:00
commit 6e3dfc45ee
12 changed files with 3157 additions and 3120 deletions

View file

@ -1,6 +0,0 @@
// Tweaks to get the Tabulator RDF library to work without Tabulator. All of this happens in the
// Zotero.RDF.AJAW namespace.
var kb = new RDFIndexedFormula();
var tabulator = {log:{debug:function(arg) {
Zotero.debug(arg, 4);
}}};

View file

@ -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
@ -12,582 +12,489 @@
// 2007 Changed so as not to munge statements from documents when smushing
//
//
/*jsl:option explicit*/
// Turn on JavaScriptLint variable declaration checking
$rdf.IndexedFormula = function () {
/*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#";
/* 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;
};
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.
*/
$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
//Stores an associative array that maps URIs to functions
$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),...]
this.classActions = []; // Array of functions to call when adding { s type X }
this.redirections = []; // redirect to lexically smaller equivalent symbol
this.aliases = []; // reverse mapping to redirection: aliases for this
this.classActions = []; // Array of functions to call when adding { s type X }
this.redirections = []; // redirect to lexically smaller equivalent symbol
this.aliases = []; // reverse mapping to redirection: aliases for this
this.HTTPRedirects = []; // redirections we got from HTTP
this.subjectIndex = []; // Array of statements with this X as subject
this.predicateIndex = []; // Array of statements with this X as subject
this.objectIndex = []; // Array of statements with this X as object
this.whyIndex = []; // Array of statements with X as provenance
this.index = [ this.subjectIndex, this.predicateIndex, this.objectIndex, this.whyIndex ];
this.subjectIndex = []; // Array of statements with this X as subject
this.predicateIndex = []; // Array of statements with this X as subject
this.objectIndex = []; // Array of statements with this X as object
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",
"InverseFunctionalProperty", "FunctionalProperty"];
// this.features = features
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);
if(formula.typeCallback != undefined)
formula.typeCallback(formula, obj, why);
var x = formula.classActions[obj.hashString()];
var done = false;
if (x) {
for (var i=0; i<x.length; i++) {
done = done || x[i](formula, subj, pred, obj, why);
}
var x = formula.classActions[obj.hashString()];
var done = false;
if(x) {
for(var i = 0; i < x.length; i++) {
done = done || x[i](formula, subj, pred, obj, why);
}
return done; // statement given is not needed if true
}
return done; // statement given is not needed if true
} //handleRDFType
//If the predicate is #type, use handleRDFType to create a typeCallback on the object
this.propertyActions[
'<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>'] = [ handleRDFType ];
this.propertyActions['<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>'] = [handleRDFType];
// Assumption: these terms are not redirected @@fixme
if (features.indexOf("sameAs") >=0)
this.propertyActions['<http://www.w3.org/2002/07/owl#sameAs>'] = [
function(formula, subj, pred, obj, why) {
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)
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)
this.classActions["<"+owl_ns+"FunctionalProperty>"] = [
function(formula, subj, proj, obj, addFn) {
return formula.newPropertyAction(subj, handle_FP);
}]; //FP => handleFP, do add to index
function handle_IFP(formula, subj, pred, obj) {
var s1 = formula.any(undefined, pred, obj);
if (s1 == undefined) return false; // First time with this value
formula.equate(s1, subj);
return true;
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
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($rdf.Util.ArrayIndexOf(features, "FunctionalProperty") >= 0)
this.classActions["<" + owl_ns + "FunctionalProperty>"] = [
function (formula, subj, proj, obj, addFn) {
return formula.newPropertyAction(subj, handle_FP);
}
]; //FP => handleFP, do add to index
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
function handle_FP(formula, subj, pred, obj) {
var o1 = formula.any(subj, pred, undefined);
if (o1 == undefined) return false; // First time with this value
formula.equate(o1, obj);
return true ;
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] = [];
if(this.propertyActions[hash] == undefined)
this.propertyActions[hash] = [];
this.propertyActions[hash].push(action);
// Now apply the function to to statements already in the store
var toBeFixed = this.statementsMatching(undefined, pred, undefined);
done = false;
for (var i=0; i<toBeFixed.length; i++) { // NOT optimized - sort toBeFixed etc
done = done || action(this, toBeFixed[i].subject, pred, toBeFixed[i].object);
var done = false;
for(var i = 0; i < toBeFixed.length; i++) { // NOT optimized - sort toBeFixed etc
done = done || action(this, toBeFixed[i].subject, pred, toBeFixed[i].object);
}
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
if(prefix=="tab" && this.namespaces["tab"]) {
return;
//See http://dig.csail.mit.edu/cgi-bin/roundup.cgi/$rdf/issue227
if(prefix == "tab" && this.namespaces["tab"]) {
return;
}
this.namespaces[prefix] = nsuri
}
}
// Deprocated ... name too generic
RDFIndexedFormula.prototype.register = function(prefix, nsuri) {
// Deprocated ... name too generic
$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}
if(!d) return true; // No information in {a = a}
var big, small;
if (d < 0) { // u1 less than u2
return this.replaceWith(u2, u1);
if(d < 0) { // u1 less than u2
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) // @@
// Replace big with small, obsoleted with obsoleting.
//
$rdf.IndexedFormula.prototype.replaceWith = function (big, small) {
//$rdf.log.debug("Replacing "+big+" with "+small) // @@
var oldhash = big.hashString();
var newhash = small.hashString();
var moveIndex = function(ix) {
var moveIndex = function (ix) {
var oldlist = ix[oldhash];
if (oldlist == undefined) return; // none to move
if(oldlist == undefined) return; // none to move
var newlist = ix[newhash];
if (newlist == undefined) {
ix[newhash] = newlist;
if(newlist == undefined) {
ix[newhash] = oldlist;
} else {
ix[newhash] = oldlist.concat(newlist);
ix[newhash] = oldlist.concat(newlist);
}
delete ix[oldhash];
}
// the canonical one carries all the indexes
for (var i=0; i<4; i++) {
moveIndex(this.index[i]);
delete ix[oldhash];
}
// the canonical one carries all the indexes
for(var i = 0; i < 4; i++) {
moveIndex(this.index[i]);
}
this.redirections[oldhash] = small;
if (big.uri) {
if (this.aliases[newhash] == undefined)
this.aliases[newhash] = [];
this.aliases[newhash].push(big); // Back link
if(big.uri) {
//@@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/2006/link#uri'), big.uri)
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)
}
// 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)
return true; // true means the statement does not need to be put in
};
//$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) {
if (term == undefined) return term;
// Return the symbol with canonical URI as smushed
$rdf.IndexedFormula.prototype.canon = function (term) {
if(term == undefined) return term;
var y = this.redirections[term.hashString()];
if (y == undefined) return term;
if(y == undefined) return term;
return y;
}
}
// Compare by canonical URI as smushed
RDFIndexedFormula.prototype.sameThings = function(x, y) {
if (x.sameTerm(y)) return true;
// Compare by canonical URI as smushed
$rdf.IndexedFormula.prototype.sameThings = function (x, y) {
if(x.sameTerm(y)) return true;
var x1 = this.canon(x);
// alert('x1='+x1);
if (x1 == undefined) return false;
// alert('x1='+x1);
if(x1 == undefined) return false;
var y1 = this.canon(y);
// alert('y1='+y1); //@@
if (y1 == undefined) return false;
return (x1.uri == y1.uri);
}
// alert('y1='+y1); //@@
if(y1 == undefined) return false;
return(x1.uri == y1.uri);
}
// A list of all the URIs by which this thing is known
RDFIndexedFormula.prototype.uris = function(term) {
// A list of all the URIs by which this thing is known
$rdf.IndexedFormula.prototype.uris = function (term) {
var cterm = this.canon(term)
var terms = this.aliases[cterm.hashString()];
if (!cterm.uri) return []
var res = [ cterm.uri ]
if (terms != undefined) {
for (var i=0; i<terms.length; i++) {
res.push(terms[i].uri)
}
if(!cterm.uri) return []
var res = [cterm.uri]
if(terms != undefined) {
for(var i = 0; i < terms.length; i++) {
res.push(terms[i].uri)
}
}
return res
}
}
// On input parameters, convert constants to terms
//
function RDFMakeTerm(formula,val, canonicalize) {
if (typeof val != 'object') {
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);
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;
// On input parameters, convert constants to terms
//
function RDFMakeTerm(formula, val, canonicalize) {
if(typeof val != 'object') {
if(typeof val == 'string')
return new $rdf.Literal(val);
if(typeof val == 'number')
return new $rdf.Literal(val); // @@ differet types
if(typeof val == 'boolean')
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
//defined in source.js, is this OK with identity.js only user?
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);
obj = RDFMakeTerm(this, obj);
why = RDFMakeTerm(this, 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);
var hash = [this.canon(subj).hashString(), this.canon(pred).hashString(),
this.canon(obj).hashString(), this.canon(why).hashString()];
if(this.predicateCallback != undefined)
this.predicateCallback(this, pred, why);
// Action return true if the statement does not need to be added
var actions = this.propertyActions[hash[1]]; // Predicate hash
var done = false;
if (actions) {
// alert('type: '+typeof actions +' @@ actions='+actions);
for (var i=0; i<actions.length; i++) {
done = done || actions[i](this, subj, pred, obj, why);
}
if(actions) {
// alert('type: '+typeof actions +' @@ actions='+actions);
for(var i = 0; i < actions.length; i++) {
done = done || actions[i](this, 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
// still return this statement for owl:sameAs input
var st = new RDFStatement(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
//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 $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, 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) {
}; //add
// Find out whether a given URI is used as symbol in the formula
$rdf.IndexedFormula.prototype.mentionsURI = function (uri) {
var hash = '<' + uri + '>';
return (!!this.subjectIndex[hash] || !!this.objectIndex[hash]
|| !!this.predicateIndex[hash]);
}
return (!!this.subjectIndex[hash]
|| !!this.objectIndex[hash]
|| !!this.predicateIndex[hash]);
}
// 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) {
for(var i=0;;i++) {
var uri = doc.uri + '#n' + i;
if (!this.mentionsURI(uri)) return kb.sym(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)) )
$rdf.IndexedFormula.prototype.nextSymbol = function (doc) {
for(var i = 0;; i++) {
var uri = doc.uri + '#n' + i;
if(!this.mentionsURI(uri)) return this.sym(uri);
}
}
}
RDFIndexedFormula.prototype.anyStatementMatching = function(subj,pred,obj,why) {
var x = this.statementsMatching(subj,pred,obj,why,true);
if (!x || x == []) return undefined;
$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];
};
};
// 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+"}");
var pat = [ subj, pred, obj, why ];
// Return statements matching a pattern
// ALL CONVENIENCE LOOKUP FUNCTIONS RELY ON THIS!
$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 = [];
var hash = [];
var wild = []; // wildcards
var given = []; // Not wild
for (var p=0; p<4; p++) {
pattern[p] = this.canon(RDFMakeTerm(this, pat[p]));
if (pattern[p] == undefined) {
wild.push(p);
} else {
given.push(p);
hash[p] = pattern[p].hashString();
}
for(var p = 0; p < 4; p++) {
pattern[p] = this.canon(RDFMakeTerm(this, pat[p]));
if(pattern[p] == undefined) {
wild.push(p);
} else {
given.push(p);
hash[p] = pattern[p].hashString();
}
}
if (given.length == 0) return this.statements; // Easy
if (given.length == 1) { // Easy too, we have an index for that
var p = given[0];
var list = this.index[p][hash[p]];
return list == undefined ? [] : list;
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;
}
// Now given.length is 2, 3 or 4.
// We hope that the scale-free nature of the data will mean we tend to get
// a short index in there somewhere!
var best = 1e10; // really bad
var best_i;
for (var i=0; i<given.length; i++) {
var p = given[i]; // Which part we are dealing with
var list = this.index[p][hash[p]];
if (list == undefined) return []; // No occurrences
if (list.length < best) {
best = list.length;
best_i = i; // (not p!)
}
for(var i = 0; i < given.length; i++) {
var p = given[i]; // Which part we are dealing with
var list = this.index[p][hash[p]];
if(list == undefined) return []; // No occurrences
if(list.length < best) {
best = list.length;
best_i = i; // (not p!)
}
}
// Ok, we have picked the shortest index but now we have to filter it
var best_p = given[best_i];
var possibles = this.index[best_p][hash[best_p]];
var check = given.slice(0, best_i).concat(given.slice(best_i+1)) // remove best_i
var check = given.slice(0, best_i).concat(given.slice(best_i + 1)) // remove best_i
var results = [];
var parts = [ 'subject', 'predicate', 'object', 'why'];
for (var j=0; j<possibles.length; j++) {
var st = possibles[j];
for (var i=0; i <check.length; i++) { // for each position to be checked
var p = check[i];
if (!this.canon(st[parts[p]]).sameTerm(pattern[p])) {
st = null;
break;
}
var parts = ['subject', 'predicate', 'object', 'why'];
for(var j = 0; j < possibles.length; j++) {
var st = possibles[j];
for(var i = 0; i < check.length; i++) { // for each position to be checked
var p = check[i];
if(!this.canon(st[parts[p]]).sameTerm(pattern[p])) {
st = null;
break;
}
if (st != null) results.push(st);
}
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);
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);
} else {
RDFArrayRemove(this.index[p][h], st);
}
}; // statementsMatching
/** remove a particular statement from the bank **/
$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) {
//$rdf.log.warn ("Statement removal: no index '+p+': "+st);
} else {
$rdf.Util.RDFArrayRemove(this.index[p][h], st);
}
}
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);
var sts = this.statementsMatching (subj, pred, obj, why, false);
$rdf.Util.RDFArrayRemove(this.statements, st);
}; //remove
/** remove all statements matching args (within 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
//but for perfromance consideration, it's better to just do that
//so make a copy here.
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]);
}; //removeMany
for(var i = 0; i < sts.length; i++) statements.push(sts[i]);
if(limit) statements = statements.slice(0, limit);
for(var i = 0; i < statements.length; i++) this.remove(statements[i]);
}; //removeMany
/** Utility**/
/** 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)
/* @method: copyTo
@description: replace @template with @target and add appropriate triples (no triple removed)
one-direction replication
*/
RDFIndexedFormula.prototype.copyTo = function(template,target,flags){
if (!flags) flags=[];
var statList=this.statementsMatching(template);
if (flags.indexOf('two-direction')!=-1)
statList.concat(this.statementsMatching(undefined,undefined,template));
for (var i=0;i<statList.length;i++){
var st=statList[i];
switch (st.object.termType){
case 'symbol':
this.add(target,st.predicate,st.object);
break;
case 'literal':
case 'bnode':
case 'collection':
this.add(target,st.predicate,st.object.copy(this));
}
if (flags.indexOf('delete')!=-1) this.remove(st);
*/
$rdf.IndexedFormula.prototype.copyTo = function (template, target, flags) {
if(!flags) flags = [];
var statList = this.statementsMatching(template);
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];
switch(st.object.termType) {
case 'symbol':
this.add(target, st.predicate, st.object);
break;
case 'literal':
case 'bnode':
case 'collection':
this.add(target, st.predicate, st.object.copy(this));
}
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);
};
RDFBlankNode.prototype.copy = function(formula){ //depends on the formula
var bnodeNew=new RDFBlankNode();
formula.copyTo(this,bnodeNew);
};
//for the case when you alter this.value (text modified in userinput.js)
$rdf.Literal.prototype.copy = function () {
return new $rdf.Literal(this.value, this.lang, this.datatype);
};
$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! **/
}
/** 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 = [];
if(!this._universalVariables) this._universalVariables = [];
this._universalVariables.push(x);
return x;
}
}
RDFIndexedFormula.prototype.newExistential = function(uri) {
if (!uri) return this.bnode();
$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) {
if (!this._existentialVariables) this._existentialVariables = [];
$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;
$rdf.IndexedFormula.prototype.hashString = $rdf.IndexedFormula.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
}
}
*/
// ends
return $rdf.IndexedFormula;
}();
// ends

View file

@ -0,0 +1,32 @@
/* Set up the environment before loading the rest of the files into Zotero */
Zotero.RDF.AJAW = {
Util: {
ArrayIndexOf: function (arr, item, i) {
//supported in all browsers except IE<9
return arr.indexOf(item, i);
},
RDFArrayRemove: function (a, x) { //removes all statements equal to x from a
for(var i = 0; i < a.length; i++) {
//TODO: This used to be the following, which didnt always work..why
//if(a[i] == x)
if(a[i].subject.sameTerm(x.subject)
&& a[i].predicate.sameTerm(x.predicate)
&& a[i].object.sameTerm(x.object)
&& a[i].why.sameTerm(x.why)) {
a.splice(i, 1);
return;
}
}
throw "RDFArrayRemove: Array did not contain " + x;
},
},
tabulator: {
log: {
debug: Zotero.debug,
warn: Zotero.debug
}
},
alert: Zotero.debug
};
Zotero.RDF.AJAW.$rdf = Zotero.RDF.AJAW;

View file

@ -5,76 +5,42 @@
//
// 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
$rdf.Symbol.prototype.sameTerm = function (other) {
if(!other) {
return false
}
return((this.termType == other.termType) && (this.uri == other.uri))
}
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
$rdf.BlankNode.prototype.sameTerm = function (other) {
if(!other) {
return false
}
return((this.termType == other.termType) && (this.id == other.id))
}
*/
function RDFTermMatch(pattern, term) {
if (typeof pattern == 'undefined') return true;
return pattern.sameTerm(term)
$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 && this.datatype.sameTerm(other.datatype))))
}
RDFSymbol.prototype.sameTerm = function(other) {
if (!other) { return false }
return ((this.termType == other.termType) && (this.uri == other.uri))
$rdf.Variable.prototype.sameTerm = function (other) {
if(!other) {
return false
}
return((this.termType == other.termType) && (this.uri == other.uri))
}
RDFBlankNode.prototype.sameTerm = function(other) {
if (!other) { return false }
return ((this.termType == other.termType) && (this.id == other.id))
}
$rdf.Collection.prototype.sameTerm = $rdf.BlankNode.prototype.sameTerm
RDFLiteral.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)))
}
RDFVariable.prototype.sameTerm = function (other) {
if (!other) { return false }
return((this.termType == other.termType) && (this.uri == other.uri))
}
RDFCollection.prototype.sameTerm = RDFBlankNode.prototype.sameTerm
RDFFormula.prototype.sameTerm = function (other) {
return this.hashString() == other.hashString();
$rdf.Formula.prototype.sameTerm = function (other) {
return this.hashString() == other.hashString();
}
// Comparison for ordering
//
@ -84,95 +50,95 @@ RDFFormula.prototype.sameTerm = function (other) {
// When we smush nodes we take the lowest value. This is not
// 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
$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
if(this.value > other.value) return +1
return 0
}
RDFLiteral.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
if (this.value > other.value) return +1
return 0
}
$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
if(this.uri > other.uri) return +1
return 0
}
RDFSymbol.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
if (this.uri > other.uri) return +1
return 0
}
$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
if(this.id > other.id) return +1
return 0
}
RDFBlankNode.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
if (this.id > other.id) return +1
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) {
var results = []
var st, sts = this.statementsMatching(s,p,o,w)
var i, n=sts.length
if (typeof s == 'undefined') {
for (i=0; i<n; i++) {st=sts[i]; results.push(st.subject)}
} else if (typeof p == 'undefined') {
for (i=0; i<n; i++) {st=sts[i]; results.push(st.predicate)}
} else if (typeof o == 'undefined') {
for (i=0; i<n; i++) {st=sts[i]; results.push(st.object)}
} else if (typeof w == 'undefined') {
for (i=0; i<n; i++) {st=sts[i]; results.push(st.why)}
$rdf.Formula.prototype.each = function (s, p, o, w) {
var results = []
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)
}
return results
} else if(typeof p == 'undefined') {
for(i = 0; i < n; i++) {
st = sts[i];
results.push(st.predicate)
}
} else if(typeof o == 'undefined') {
for(i = 0; i < n; i++) {
st = sts[i];
results.push(st.object)
}
} else if(typeof w == 'undefined') {
for(i = 0; i < n; i++) {
st = sts[i];
results.push(st.why)
}
}
return results
}
RDFFormula.prototype.any = function(s,p,o,w) {
var st = this.anyStatementMatching(s,p,o,w)
if (typeof st == 'undefined') return undefined;
if (typeof s == 'undefined') return st.subject;
if (typeof p == 'undefined') return st.predicate;
if (typeof o == 'undefined') return st.object;
$rdf.Formula.prototype.any = function (s, p, o, w) {
var st = this.anyStatementMatching(s, p, o, w)
if(typeof st == 'undefined') return undefined;
return undefined
if(typeof s == 'undefined') return st.subject;
if(typeof p == 'undefined') return st.predicate;
if(typeof o == 'undefined') return st.object;
return undefined
}
RDFFormula.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 + "}.")
return x
$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;
}
RDFFormula.prototype.whether = function(s,p,o,w) {
return this.statementsMatching(s,p,o,w).length;
$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')
$rdf.log.error("No value found for the(){" + s + " " + p + " " + o + "}.")
return x
}
// 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)
}
// ends
$rdf.Formula.prototype.whether = function (s, p, o, w) {
return this.statementsMatching(s, p, o, w, false).length;
}

File diff suppressed because it is too large Load diff

View file

@ -61,502 +61,504 @@
* @constructor
* @param {RDFStore} store An RDFStore object
*/
function RDFParser(store) {
/** Standard namespaces that we know how to handle @final
* @member RDFParser
*/
RDFParser['ns'] = {'RDF':
"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
'RDFS':
"http://www.w3.org/2000/01/rdf-schema#"}
/** DOM Level 2 node type magic numbers @final
* @member RDFParser
*/
RDFParser['nodeType'] = {'ELEMENT': 1, 'ATTRIBUTE': 2, 'TEXT': 3,
'CDATA_SECTION': 4, 'ENTITY_REFERENCE': 5,
'ENTITY': 6, 'PROCESSING_INSTRUCTION': 7,
'COMMENT': 8, 'DOCUMENT': 9, 'DOCUMENT_TYPE': 10,
'DOCUMENT_FRAGMENT': 11, 'NOTATION': 12}
$rdf.RDFParser = function (store) {
var RDFParser = {};
/**
* Frame class for namespace and base URI lookups
* Base lookups will always resolve because the parser knows
* the default base.
*
* @private
*/
this['frameFactory'] = function (parser, parent, element) {
return {'NODE': 1,
'ARC': 2,
'parent': parent,
'parser': parser,
'store': parser['store'],
'element': element,
'lastChild': 0,
'base': null,
'lang': null,
'node': null,
'nodeType': null,
'listIndex': 1,
'rdfid': null,
'datatype': null,
'collection': false,
/** Standard namespaces that we know how to handle @final
* @member RDFParser
*/
RDFParser['ns'] = {
'RDF': "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
'RDFS': "http://www.w3.org/2000/01/rdf-schema#"
}
/** DOM Level 2 node type magic numbers @final
* @member RDFParser
*/
RDFParser['nodeType'] = {
'ELEMENT': 1,
'ATTRIBUTE': 2,
'TEXT': 3,
'CDATA_SECTION': 4,
'ENTITY_REFERENCE': 5,
'ENTITY': 6,
'PROCESSING_INSTRUCTION': 7,
'COMMENT': 8,
'DOCUMENT': 9,
'DOCUMENT_TYPE': 10,
'DOCUMENT_FRAGMENT': 11,
'NOTATION': 12
}
/** Terminate the frame and notify the store that we're done */
'terminateFrame': function () {
if (this['collection']) {
this['node']['close']()
}
},
/** Add a symbol of a certain type to the this frame */
'addSymbol': function (type, uri) {
uri = Util.uri.join(uri, this['base'])
this['node'] = this['store']['sym'](uri)
this['nodeType'] = type
},
/** Load any constructed triples into the store */
'loadTriple': function () {
if (this['parent']['parent']['collection']) {
this['parent']['parent']['node']['append'](this['node'])
}
else {
this['store']['add'](this['parent']['parent']['node'],
this['parent']['node'],
this['node'],
this['parser']['why'])
}
if (this['parent']['rdfid'] != null) { // reify
var triple = this['store']['sym'](
Util.uri.join("#"+this['parent']['rdfid'],
this['base']))
this['store']['add'](triple,
this['store']['sym'](
RDFParser['ns']['RDF']
+"type"),
this['store']['sym'](
RDFParser['ns']['RDF']
+"Statement"),
this['parser']['why'])
this['store']['add'](triple,
this['store']['sym'](
RDFParser['ns']['RDF']
+"subject"),
this['parent']['parent']['node'],
this['parser']['why'])
this['store']['add'](triple,
this['store']['sym'](
RDFParser['ns']['RDF']
+"predicate"),
this['parent']['node'],
this['parser']['why'])
this['store']['add'](triple,
this['store']['sym'](
RDFParser['ns']['RDF']
+"object"),
this['node'],
this['parser']['why'])
}
},
/**
* Frame class for namespace and base URI lookups
* Base lookups will always resolve because the parser knows
* the default base.
*
* @private
*/
this['frameFactory'] = function (parser, parent, element) {
return {
'NODE': 1,
'ARC': 2,
'parent': parent,
'parser': parser,
'store': parser['store'],
'element': element,
'lastChild': 0,
'base': null,
'lang': null,
'node': null,
'nodeType': null,
'listIndex': 1,
'rdfid': null,
'datatype': null,
'collection': false,
/** Check if it's OK to load a triple */
'isTripleToLoad': function () {
return (this['parent'] != null
&& this['parent']['parent'] != null
&& this['nodeType'] == this['NODE']
&& this['parent']['nodeType'] == this['ARC']
&& this['parent']['parent']['nodeType']
== this['NODE'])
},
/** Terminate the frame and notify the store that we're done */
'terminateFrame': function () {
if(this['collection']) {
this['node']['close']()
}
},
/** Add a symbolic node to this frame */
'addNode': function (uri) {
this['addSymbol'](this['NODE'],uri)
if (this['isTripleToLoad']()) {
this['loadTriple']()
}
},
/** Add a symbol of a certain type to the this frame */
'addSymbol': function (type, uri) {
uri = $rdf.Util.uri.join(uri, this['base'])
this['node'] = this['store']['sym'](uri)
this['nodeType'] = type
},
/** Add a collection node to this frame */
'addCollection': function () {
this['nodeType'] = this['NODE']
this['node'] = this['store']['collection']()
this['collection'] = true
if (this['isTripleToLoad']()) {
this['loadTriple']()
}
},
/** Load any constructed triples into the store */
'loadTriple': function () {
if(this['parent']['parent']['collection']) {
this['parent']['parent']['node']['append'](this['node'])
} else {
this['store']['add'](this['parent']['parent']['node'],
this['parent']['node'],
this['node'],
this['parser']['why'])
}
if(this['parent']['rdfid'] != null) { // reify
var triple = this['store']['sym'](
$rdf.Util.uri.join("#" + this['parent']['rdfid'], this['base']))
this['store']['add'](triple,
this['store']['sym'](RDFParser['ns']['RDF'] + "type"),
this['store']['sym'](RDFParser['ns']['RDF'] + "Statement"),
this['parser']['why'])
this['store']['add'](triple,
this['store']['sym'](RDFParser['ns']['RDF'] + "subject"),
this['parent']['parent']['node'],
this['parser']['why'])
this['store']['add'](triple,
this['store']['sym'](RDFParser['ns']['RDF'] + "predicate"),
this['parent']['node'],
this['parser']['why'])
this['store']['add'](triple,
this['store']['sym'](RDFParser['ns']['RDF'] + "object"),
this['node'],
this['parser']['why'])
}
},
/** Add a collection arc to this frame */
'addCollectionArc': function () {
this['nodeType'] = this['ARC']
},
/** Check if it's OK to load a triple */
'isTripleToLoad': function () {
return (this['parent'] != null
&& this['parent']['parent'] != null
&& this['nodeType'] == this['NODE']
&& this['parent']['nodeType'] == this['ARC']
&& this['parent']['parent']['nodeType'] == this['NODE'])
},
/** Add a bnode to this frame */
'addBNode': function (id) {
if (id != null) {
if (this['parser']['bnodes'][id] != null) {
this['node'] = this['parser']['bnodes'][id]
} else {
this['node'] = this['parser']['bnodes'][id] = this['store']['bnode']()
}
} else { this['node'] = this['store']['bnode']() }
this['nodeType'] = this['NODE']
if (this['isTripleToLoad']()) {
this['loadTriple']()
}
},
/** Add a symbolic node to this frame */
'addNode': function (uri) {
this['addSymbol'](this['NODE'], uri)
if(this['isTripleToLoad']()) {
this['loadTriple']()
}
},
/** Add an arc or property to this frame */
'addArc': function (uri) {
if (uri == RDFParser['ns']['RDF']+"li") {
uri = RDFParser['ns']['RDF']+"_"+this['parent']['listIndex']++
}
this['addSymbol'](this['ARC'], uri)
},
/** Add a collection node to this frame */
'addCollection': function () {
this['nodeType'] = this['NODE']
this['node'] = this['store']['collection']()
this['collection'] = true
if(this['isTripleToLoad']()) {
this['loadTriple']()
}
},
/** Add a literal to this frame */
'addLiteral': function (value) {
if (this['parent']['datatype']) {
this['node'] = this['store']['literal'](
value, "", this['store']['sym'](
this['parent']['datatype']))
}
else {
this['node'] = this['store']['literal'](
value, this['lang'])
}
this['nodeType'] = this['NODE']
if (this['isTripleToLoad']()) {
this['loadTriple']()
}
}
}
/** Add a collection arc to this frame */
'addCollectionArc': function () {
this['nodeType'] = this['ARC']
},
/** Add a bnode to this frame */
'addBNode': function (id) {
if(id != null) {
if(this['parser']['bnodes'][id] != null) {
this['node'] = this['parser']['bnodes'][id]
} else {
this['node'] = this['parser']['bnodes'][id] = this['store']['bnode']()
}
} else {
this['node'] = this['store']['bnode']()
}
this['nodeType'] = this['NODE']
if(this['isTripleToLoad']()) {
this['loadTriple']()
}
},
/** Add an arc or property to this frame */
'addArc': function (uri) {
if(uri == RDFParser['ns']['RDF'] + "li") {
uri = RDFParser['ns']['RDF'] + "_" + this['parent']['listIndex']++
}
this['addSymbol'](this['ARC'], uri)
},
/** Add a literal to this frame */
'addLiteral': function (value) {
if(this['parent']['datatype']) {
this['node'] = this['store']['literal'](
value, "", this['store']['sym'](
this['parent']['datatype']))
} else {
this['node'] = this['store']['literal'](
value, this['lang'])
}
this['nodeType'] = this['NODE']
if(this['isTripleToLoad']()) {
this['loadTriple']()
}
}
}
}
//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 */
this['bnodes'] = {}
/** A context for context-aware stores @private */
this['why'] = null
/** Reification flag */
this['reify'] = false
/**
* Build our initial scope frame and parse the DOM into triples
* @param {DOMTree} document The DOM to parse
* @param {String} base The base URL to use
* @param {Object} why The context to which this resource belongs
*/
this['parse'] = function (document, base, why) {
// alert('parse base:'+base);
var children = document['childNodes']
// clean up for the next run
this['cleanParser']()
// figure out the root element
//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'] == RDFParser['nodeType']['ELEMENT']) {
var root = children[c]
break
}
}
} else if(document['nodeType'] == RDFParser['nodeType']['ELEMENT']) {
var root = document
} else {
throw new Error("RDFParser: can't find root in " + base + ". Halting. ")
return false
}
/** Our triple store reference @private */
this['store'] = store
/** Our identified blank nodes @private */
this['bnodes'] = {}
/** A context for context-aware stores @private */
this['why'] = null
/** Reification flag */
this['reify'] = false
this['why'] = why
/**
* Build our initial scope frame and parse the DOM into triples
* @param {DOMTree} document The DOM to parse
* @param {String} base The base URL to use
* @param {Object} why The context to which this resource belongs
*/
this['parse'] = function (document, base, why) {
// alert('parse base:'+base);
var children = document['childNodes']
// clean up for the next run
this['cleanParser']()
// our topmost frame
var f = this['frameFactory'](this)
this['base'] = base
f['base'] = base
f['lang'] = ''
// figure out the root element
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']
== RDFParser['nodeType']['ELEMENT']) {
var root = children[c]
break
}
}
}
else if (document['nodeType'] == RDFParser['nodeType']['ELEMENT']) {
var root = document
}
else {
throw new Error("RDFParser: can't find root in " + base
+ ". Halting. ")
return false
}
*/
this['why'] = why
this['parseDOM'](this['buildFrame'](f, root))
return true
}
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)
}
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
while(frame['parent']) {
var dom = frame['element']
var attrs = dom['attributes']
// our topmost frame
var f = this['frameFactory'](this)
this['base'] = base
f['base'] = base
f['lang'] = ''
this['parseDOM'](this['buildFrame'](f,root))
return true
}
this['parseDOM'] = function (frame) {
// a DOM utility function used in parsing
var elementURI = function (el) {
if (el['namespaceURI'] == null) {
throw new Error("RDF/XML syntax error: No namespace for "
+el['localName']+" in "+this.base)
if(dom['nodeType'] == RDFParser['nodeType']['TEXT']
|| dom['nodeType'] == RDFParser['nodeType']['CDATA_SECTION']) {
//we have a literal
frame['addLiteral'](dom['nodeValue'])
} else if(elementURI(dom) != RDFParser['ns']['RDF'] + "RDF") {
// not root
if(frame['parent'] && frame['parent']['collection']) {
// we're a collection element
frame['addCollectionArc']()
frame = this['buildFrame'](frame, frame['element'])
frame['parent']['element'] = null
}
if(!frame['parent'] || !frame['parent']['nodeType']
|| frame['parent']['nodeType'] == frame['ARC']) {
// we need a node
var about = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "about")
var rdfid = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "ID")
if(about && rdfid) {
throw new Error("RDFParser: " + dom['nodeName']
+ " has both rdf:id and rdf:about." + " Halting. Only one of these"
+ " properties may be specified on a" + " node.");
}
if(about == null && rdfid) {
frame['addNode']("#" + rdfid['nodeValue'])
dom['removeAttributeNode'](rdfid)
} else if(about == null && rdfid == null) {
var bnid = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "nodeID")
if(bnid) {
frame['addBNode'](bnid['nodeValue'])
dom['removeAttributeNode'](bnid)
} else {
frame['addBNode']()
}
return el['namespaceURI'] + el['localName']
}
var dig = true // if we'll dig down in the tree on the next iter
} else {
frame['addNode'](about['nodeValue'])
dom['removeAttributeNode'](about)
}
while (frame['parent']) {
var dom = frame['element']
var attrs = dom['attributes']
// Typed nodes
var rdftype = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "type")
if(RDFParser['ns']['RDF'] + "Description" != elementURI(dom)) {
rdftype = {
'nodeValue': elementURI(dom)
}
}
if(rdftype != null) {
this['store']['add'](frame['node'],
this['store']['sym'](RDFParser['ns']['RDF'] + "type"),
this['store']['sym'](
$rdf.Util.uri.join(
rdftype['nodeValue'],
frame['base'])),
this['why'])
if(rdftype['nodeName']) {
dom['removeAttributeNode'](rdftype)
}
}
if (dom['nodeType']
== RDFParser['nodeType']['TEXT']
|| dom['nodeType']
== RDFParser['nodeType']['CDATA_SECTION']) {//we have a literal
frame['addLiteral'](dom['nodeValue'])
}
else if (elementURI(dom)
!= RDFParser['ns']['RDF']+"RDF") { // not root
if (frame['parent'] && frame['parent']['collection']) {
// we're a collection element
frame['addCollectionArc']()
frame = this['buildFrame'](frame,frame['element'])
frame['parent']['element'] = null
}
if (!frame['parent'] || !frame['parent']['nodeType']
|| frame['parent']['nodeType'] == frame['ARC']) {
// we need a node
var about =dom['getAttributeNodeNS'](
RDFParser['ns']['RDF'],"about")
var rdfid =dom['getAttributeNodeNS'](
RDFParser['ns']['RDF'],"ID")
if (about && rdfid) {
throw new Error("RDFParser: " + dom['nodeName']
+ " has both rdf:id and rdf:about."
+ " Halting. Only one of these"
+ " properties may be specified on a"
+ " node.");
}
if (about == null && rdfid) {
frame['addNode']("#"+rdfid['nodeValue'])
dom['removeAttributeNode'](rdfid)
}
else if (about == null && rdfid == null) {
var bnid = dom['getAttributeNodeNS'](
RDFParser['ns']['RDF'],"nodeID")
if (bnid) {
frame['addBNode'](bnid['nodeValue'])
dom['removeAttributeNode'](bnid)
} else { frame['addBNode']() }
}
else {
frame['addNode'](about['nodeValue'])
dom['removeAttributeNode'](about)
}
// Typed nodes
var rdftype = dom['getAttributeNodeNS'](
RDFParser['ns']['RDF'],"type")
if (RDFParser['ns']['RDF']+"Description"
!= elementURI(dom)) {
rdftype = {'nodeValue': elementURI(dom)}
}
if (rdftype != null) {
this['store']['add'](frame['node'],
this['store']['sym'](
RDFParser['ns']['RDF']+"type"),
this['store']['sym'](
Util.uri.join(
rdftype['nodeValue'],
frame['base'])),
this['why'])
if (rdftype['nodeName']){
dom['removeAttributeNode'](rdftype)
}
}
// Property Attributes
for (var x = attrs['length']-1; x >= 0; x--) {
this['store']['add'](frame['node'],
this['store']['sym'](
elementURI(attrs[x])),
this['store']['literal'](
attrs[x]['nodeValue'],
frame['lang']),
this['why'])
}
}
else { // we should add an arc (or implicit bnode+arc)
frame['addArc'](elementURI(dom))
// Property Attributes
for(var x = attrs['length'] - 1; x >= 0; x--) {
this['store']['add'](frame['node'],
this['store']['sym'](elementURI(attrs[x])),
this['store']['literal'](
attrs[x]['nodeValue'],
frame['lang']),
this['why'])
}
} else {
// we should add an arc (or implicit bnode+arc)
frame['addArc'](elementURI(dom))
// save the arc's rdf:ID if it has one
if (this['reify']) {
var rdfid = dom['getAttributeNodeNS'](
RDFParser['ns']['RDF'],"ID")
if (rdfid) {
frame['rdfid'] = rdfid['nodeValue']
dom['removeAttributeNode'](rdfid)
}
}
// save the arc's rdf:ID if it has one
if(this['reify']) {
var rdfid = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "ID")
if(rdfid) {
frame['rdfid'] = rdfid['nodeValue']
dom['removeAttributeNode'](rdfid)
}
}
var parsetype = dom['getAttributeNodeNS'](
RDFParser['ns']['RDF'],"parseType")
var datatype = dom['getAttributeNodeNS'](
RDFParser['ns']['RDF'],"datatype")
if (datatype) {
frame['datatype'] = datatype['nodeValue']
dom['removeAttributeNode'](datatype)
}
var parsetype = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "parseType")
var datatype = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "datatype")
if(datatype) {
frame['datatype'] = datatype['nodeValue']
dom['removeAttributeNode'](datatype)
}
if (parsetype) {
var nv = parsetype['nodeValue']
if (nv == "Literal") {
frame['datatype']
= RDFParser['ns']['RDF']+"XMLLiteral"
// (this.buildFrame(frame)).addLiteral(dom)
// should work but doesn't
frame = this['buildFrame'](frame)
frame['addLiteral'](dom)
dig = false
}
else if (nv == "Resource") {
frame = this['buildFrame'](frame,frame['element'])
frame['parent']['element'] = null
frame['addBNode']()
}
else if (nv == "Collection") {
frame = this['buildFrame'](frame,frame['element'])
frame['parent']['element'] = null
frame['addCollection']()
}
dom['removeAttributeNode'](parsetype)
}
if(parsetype) {
var nv = parsetype['nodeValue']
if(nv == "Literal") {
frame['datatype'] = RDFParser['ns']['RDF'] + "XMLLiteral"
// (this.buildFrame(frame)).addLiteral(dom)
// should work but doesn't
frame = this['buildFrame'](frame)
frame['addLiteral'](dom)
dig = false
} else if(nv == "Resource") {
frame = this['buildFrame'](frame, frame['element'])
frame['parent']['element'] = null
frame['addBNode']()
} else if(nv == "Collection") {
frame = this['buildFrame'](frame, frame['element'])
frame['parent']['element'] = null
frame['addCollection']()
}
dom['removeAttributeNode'](parsetype)
}
if (attrs['length'] != 0) {
var resource = dom['getAttributeNodeNS'](
RDFParser['ns']['RDF'],"resource")
var bnid = dom['getAttributeNodeNS'](
RDFParser['ns']['RDF'],"nodeID")
if(attrs['length'] != 0) {
var resource = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "resource")
var bnid = this['getAttributeNodeNS'](dom, RDFParser['ns']['RDF'], "nodeID")
frame = this['buildFrame'](frame)
if (resource) {
frame['addNode'](resource['nodeValue'])
dom['removeAttributeNode'](resource)
} else {
if (bnid) {
frame['addBNode'](bnid['nodeValue'])
dom['removeAttributeNode'](bnid)
} else { frame['addBNode']() }
}
frame = this['buildFrame'](frame)
if(resource) {
frame['addNode'](resource['nodeValue'])
dom['removeAttributeNode'](resource)
} else {
if(bnid) {
frame['addBNode'](bnid['nodeValue'])
dom['removeAttributeNode'](bnid)
} else {
frame['addBNode']()
}
}
for (var x = attrs['length']-1; x >= 0; x--) {
var f = this['buildFrame'](frame)
f['addArc'](elementURI(attrs[x]))
if (elementURI(attrs[x])
==RDFParser['ns']['RDF']+"type"){
(this['buildFrame'](f))['addNode'](
attrs[x]['nodeValue'])
} else {
(this['buildFrame'](f))['addLiteral'](
attrs[x]['nodeValue'])
}
}
}
else if (dom['childNodes']['length'] == 0) {
(this['buildFrame'](frame))['addLiteral']("")
}
}
} // rdf:RDF
for(var x = attrs['length'] - 1; x >= 0; x--) {
var f = this['buildFrame'](frame)
f['addArc'](elementURI(attrs[x]))
if(elementURI(attrs[x]) == RDFParser['ns']['RDF'] + "type") {
(this['buildFrame'](f))['addNode'](
attrs[x]['nodeValue'])
} else {
(this['buildFrame'](f))['addLiteral'](
attrs[x]['nodeValue'])
}
}
} else if(dom['childNodes']['length'] == 0) {
(this['buildFrame'](frame))['addLiteral']("")
}
}
} // rdf:RDF
// dig dug
dom = frame['element']
while(frame['parent']) {
var pframe = frame
while(dom == null) {
frame = frame['parent']
dom = frame['element']
}
var candidate = dom['childNodes'][frame['lastChild']]
if(candidate == null || !dig) {
frame['terminateFrame']()
if(!(frame = frame['parent'])) {
break
} // done
dom = frame['element']
dig = true
} else if((candidate['nodeType'] != RDFParser['nodeType']['ELEMENT']
&& candidate['nodeType'] != RDFParser['nodeType']['TEXT']
&& candidate['nodeType'] != RDFParser['nodeType']['CDATA_SECTION'])
|| ((candidate['nodeType'] == RDFParser['nodeType']['TEXT']
|| candidate['nodeType'] == RDFParser['nodeType']['CDATA_SECTION'])
&& dom['childNodes']['length'] != 1)) {
frame['lastChild']++
} else {
// not a leaf
frame['lastChild']++;
frame = this['buildFrame'](pframe, dom['childNodes'][frame['lastChild'] - 1])
break
}
}
} // while
}
// dig dug
dom = frame['element']
while (frame['parent']) {
var pframe = frame
while (dom == null) {
frame = frame['parent']
dom = frame['element']
}
var candidate = dom['childNodes'][frame['lastChild']]
if (candidate == null || !dig) {
frame['terminateFrame']()
if (!(frame = frame['parent'])) { break } // done
dom = frame['element']
dig = true
}
else if ((candidate['nodeType']
!= RDFParser['nodeType']['ELEMENT']
&& candidate['nodeType']
!= RDFParser['nodeType']['TEXT']
&& candidate['nodeType']
!= RDFParser['nodeType']['CDATA_SECTION'])
|| ((candidate['nodeType']
== RDFParser['nodeType']['TEXT']
|| candidate['nodeType']
== RDFParser['nodeType']['CDATA_SECTION'])
&& dom['childNodes']['length'] != 1)) {
frame['lastChild']++
}
else { // not a leaf
frame['lastChild']++
frame = this['buildFrame'](pframe,
dom['childNodes'][frame['lastChild']-1])
break
}
}
} // while
/**
* Cleans out state from a previous parse run
* @private
*/
this['cleanParser'] = function () {
this['bnodes'] = {}
this['why'] = null
}
/**
* Builds scope frame
* @private
*/
this['buildFrame'] = function (parent, element) {
var frame = this['frameFactory'](this, parent, element)
if(parent) {
frame['base'] = parent['base']
frame['lang'] = parent['lang']
}
if(element == null
|| element['nodeType'] == RDFParser['nodeType']['TEXT']
|| element['nodeType'] == RDFParser['nodeType']['CDATA_SECTION']) {
return frame
}
/**
* Cleans out state from a previous parse run
* @private
*/
this['cleanParser'] = function () {
this['bnodes'] = {}
this['why'] = null
var attrs = element['attributes']
var base = element['getAttributeNode']("xml:base")
if(base != null) {
frame['base'] = base['nodeValue']
element['removeAttribute']("xml:base")
}
var lang = element['getAttributeNode']("xml:lang")
if(lang != null) {
frame['lang'] = lang['nodeValue']
element['removeAttribute']("xml:lang")
}
/**
* Builds scope frame
* @private
*/
this['buildFrame'] = function (parent, element) {
var frame = this['frameFactory'](this,parent,element)
if (parent) {
frame['base'] = parent['base']
frame['lang'] = parent['lang']
}
if (element == null
|| element['nodeType'] == RDFParser['nodeType']['TEXT']
|| element['nodeType'] == RDFParser['nodeType']['CDATA_SECTION']) {
return frame
}
var attrs = element['attributes']
var base = element['getAttributeNode']("xml:base")
if (base != null) {
frame['base'] = base['nodeValue']
element['removeAttribute']("xml:base")
}
var lang = element['getAttributeNode']("xml:lang")
if (lang != null) {
frame['lang'] = lang['nodeValue']
element['removeAttribute']("xml:lang")
}
// remove all extraneous xml and xmlns attributes
for (var x = attrs['length']-1; x >= 0; x--) {
if (attrs[x]['nodeName']['substr'](0,3) == "xml") {
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);
this.store.setPrefixForURI(attrs[x].name.slice(6),
uri);
}
// alert('rdfparser: xml atribute: '+attrs[x].name) //@@
element['removeAttributeNode'](attrs[x])
}
}
return frame
// remove all extraneous xml and xmlns attributes
for(var x = attrs['length'] - 1; x >= 0; x--) {
if(attrs[x]['nodeName']['substr'](0, 3) == "xml") {
if(attrs[x].name.slice(0, 6) == 'xmlns:') {
var uri = attrs[x].nodeValue;
// alert('base for namespac attr:'+this.base);
if(this.base) uri = $rdf.Util.uri.join(uri, this.base);
this.store.setPrefixForURI(attrs[x].name.slice(6), uri);
}
// alert('rdfparser: xml atribute: '+attrs[x].name) //@@
element['removeAttributeNode'](attrs[x])
}
}
return frame
}
}

File diff suppressed because it is too large Load diff

View file

@ -7,139 +7,161 @@
//
// 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
$rdf.Empty = function () {
return this;
};
function RDFEmpty() {
return this;
}
RDFEmpty.prototype.termType = 'empty'
RDFEmpty.prototype.toString = function () { return "()" }
RDFEmpty.prototype.toNT = function () { return "@@" }
$rdf.Empty.prototype.termType = 'empty';
$rdf.Empty.prototype.toString = function () {
return "()"
};
$rdf.Empty.prototype.toNT = $rdf.Empty.prototype.toString;
function RDFSymbol_toNT(x) {
return ("<" + x.uri + ">")
$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
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";
var RDFNextId = 0; // Gobal genid
RDFGenidPrefix = "genid:"
NTAnonymousNodePrefix = "_:n"
function RDFBlankNode(id) {
/*if (id)
$rdf.BlankNode = function (id) {
/*if (id)
this.id = id;
else*/
this.id = RDFNextId++
return this
}
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) {
this.value = value
this.lang=lang; // string
this.datatype=datatype; // term
this.toString = RDFLiteralToString
this.toNT = RDFLiteral_toNT
return this
$rdf.Literal = function (value, lang, datatype) {
this.value = value
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'
$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 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()
}
if(this.lang) {
str = str + "@" + this.lang;
}
return str;
};
function RDFLiteral_toNT() {
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 + '"' //'
$rdf.Collection = function () {
this.id = $rdf.NextId++; // Why need an id? For hashstring.
this.elements = [];
this.closed = false;
};
if (this.datatype){
str = str + '^^' + this.datatype//.toNT()
}
if (this.lang) {
str = str + "@" + this.lang
}
return str
$rdf.Collection.prototype.termType = 'collection';
$rdf.Collection.prototype.toNT = function () {
return $rdf.NTAnonymousNodePrefix + this.id
};
$rdf.Collection.prototype.toString = function () {
var str = '(';
for(var i = 0; i < this.elements.length; i++)
str += this.elements[i] + ' ';
return str + ')';
};
$rdf.Collection.prototype.append = function (el) {
this.elements.push(el)
}
$rdf.Collection.prototype.unshift = function (el) {
this.elements.unshift(el);
}
$rdf.Collection.prototype.shift = function () {
return this.elements.shift();
}
function RDFLiteralToString() {
return ''+this.value
}
RDFLiteral.prototype.toString = RDFLiteralToString
RDFLiteral.prototype.toNT = RDFLiteral_toNT
function RDFCollection() {
this.id = RDFNextId++
this.elements = []
this.closed = false
$rdf.Collection.prototype.close = function () {
this.closed = true
}
RDFCollection.prototype.termType = 'collection'
RDFCollection.prototype.toNT = function() {
return NTAnonymousNodePrefix + this.id
}
RDFCollection.prototype.toString = RDFCollection.prototype.toNT
// 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);
RDFCollection.prototype.append = function (el) {
this.elements.push(el)
}
RDFCollection.prototype.unshift=function(el){
this.elements.unshift(el);
}
RDFCollection.prototype.shift=function(){
return this.elements.shift();
}
RDFCollection.prototype.close = function () {
this.closed = true
} 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
@ -148,144 +170,133 @@ RDFCollection.prototype.close = function () {
//
// The reason can point to provenece or inference
//
function RDFStatement_toNT() {
return (this.subject.toNT() + " "
+ this.predicate.toNT() + " "
+ this.object.toNT() +" .")
$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;
}
return this;
}
function RDFStatement(subject, predicate, object, why) {
this.subject = makeTerm(subject)
this.predicate = makeTerm(predicate)
this.object = makeTerm(object)
if (typeof why !='undefined') {
this.why = why
} else if (RDFTracking) {
tabulator.log.debug("WARNING: No reason on "+subject+" "+predicate+" "+object)
}
return this
}
$rdf.st = function (subject, predicate, object, why) {
return new $rdf.Statement(subject, predicate, object, why);
};
RDFStatement.prototype.toNT = RDFStatement_toNT
RDFStatement.prototype.toString = RDFStatement_toNT
$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.
$rdf.Formula = function () {
this.statements = []
this.constraints = []
this.initBindings = []
this.optional = []
return this;
};
function RDFFormula() {
this.statements = []
this.constraints = []
this.initBindings = []
this.optional = []
this.superFormula = null;
return this
}
function RDFFormula_toNT() {
// throw 'Who called me?';
return "{" + this.statements.join('\n') + "}"
}
$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:
$rdf.Formula.prototype.sym = function (uri, name) {
if(name != null) {
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 $rdf.Symbol(uri)
}
RDFFormula.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
$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)
}
$rdf.Formula.prototype.formula = function () {
return new $rdf.Formula()
}
$rdf.Formula.prototype.collection = function () { // obsolete
return new $rdf.Collection()
}
$rdf.Formula.prototype.list = function (values) {
var li = new $rdf.Collection();
if(values) {
for(var i = 0; i < values.length; i++) {
li.append(values[i]);
}
return new RDFSymbol(uri)
}
return li;
}
RDFFormula.prototype.literal = function(val, lang, dt) {
return new RDFLiteral(val.toString(), lang, dt)
}
RDFFormula.prototype.bnode = function(id) {
return new RDFBlankNode(id)
}
RDFFormula.prototype.formula = function() {
return new RDFFormula()
}
RDFFormula.prototype.collection = function () { // obsolete
return new RDFCollection()
}
RDFFormula.prototype.list = function (values) {
li = new RDFCollection();
if (values) {
for(var i = 0; i<values.length; i++) {
li.append(values[i]);
}
}
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.
*/
**
** 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. 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);
return this;
$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
return '?' + this.uri;
$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 +304,43 @@ 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.
RDFFormula.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 == '_') {
var x = new RDFBlankNode();
x.id = parseInt(str.slice(3));
RDFNextId--
return x
// This will only parse the strings generated by the vaious toNT() methods.
$rdf.Formula.prototype.fromNT = function (str) {
var len = str.length
var ch = str.slice(0, 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
}
throw "Can't convert from NT"+str;
//alert("Can't yet convert from NT: '"+str+"', "+str[0])
}
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 $rdf.BlankNode();
x.id = parseInt(str.slice(3));
$rdf.NextId--
return x
}
if(ch == '?') {
var x = new $rdf.Variable(str.slice(1));
return x;
}
throw "Can't convert from NT: " + str;
// ends
}
$rdf.fromNT = $rdf.Formula.prototype.fromNT; // Not for inexpert user
// Convenience - and more conventional name:
$rdf.graph = function () {
return new $rdf.IndexedFormula();
};
// ends

View file

@ -11,133 +11,139 @@
//
// See also http://www.w3.org/2000/10/swap/uripath.py
//
if(typeof $rdf.Util.uri == "undefined") {
$rdf.Util.uri = {};
};
if (typeof Util == "undefined") { Util = {}}
if (typeof Util.uri == "undefined") { Util.uri = {}}
Util.uri.join = function (given, base) {
// if (typeof tabulator.log.debug != 'undefined') tabulator.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
if (given.indexOf('#')==0) return base + given
var colon = given.indexOf(':')
if (colon >= 0) return given // Absolute URI form overrides base URI
var baseColon = base.indexOf(':')
if (base == "") return given;
if (baseColon < 0) {
alert("Invalid base: "+ base + ' in join with ' +given);
return given
$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
if(given.indexOf('#') == 0) return base + given
var colon = given.indexOf(':')
if(colon >= 0) return given // Absolute URI form overrides base URI
var baseColon = base.indexOf(':')
if(base == "") return given;
if(baseColon < 0) {
alert("Invalid base: " + base + ' in join with ' + given);
return given
}
var baseScheme = base.slice(0, baseColon + 1) // eg http:
if(given.indexOf("//") == 0) // Starts with //
return baseScheme + given;
if(base.indexOf('//', baseColon) == baseColon + 1) { // Any hostpart?
var baseSingle = base.indexOf("/", baseColon + 3)
if(baseSingle < 0) {
if(base.length - baseColon - 3 > 0) {
return base + "/" + given
} else {
return baseScheme + given
}
}
var baseScheme = base.slice(0,baseColon+1) // eg http:
if (given.indexOf("//") == 0) // Starts with //
return baseScheme + given;
if (base.indexOf('//', baseColon)==baseColon+1) { // Any hostpart?
var baseSingle = base.indexOf("/", baseColon+3)
if (baseSingle < 0) {
if (base.length-baseColon-3 > 0) {
return base + "/" + given
} else {
return baseScheme + given
}
}
} else {
var baseSingle = base.indexOf("/", baseColon+1)
if (baseSingle < 0) {
if (base.length-baseColon-1 > 0) {
return base + "/" + given
} else {
return baseScheme + given
}
}
} else {
var baseSingle = base.indexOf("/", baseColon + 1)
if(baseSingle < 0) {
if(base.length - baseColon - 1 > 0) {
return base + "/" + given
} else {
return baseScheme + given
}
}
}
if (given.indexOf('/') == 0) // starts with / but not //
return base.slice(0, baseSingle) + given
var path = base.slice(baseSingle)
var lastSlash = path.lastIndexOf("/")
if (lastSlash <0) return baseScheme + given
if ((lastSlash >=0) && (lastSlash < (path.length-1)))
path = path.slice(0, lastSlash+1) // Chop trailing filename from 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( /\/\.$/, '/' )
return base.slice(0, baseSingle) + path
if(given.indexOf('/') == 0) // starts with / but not //
return base.slice(0, baseSingle) + given
var path = base.slice(baseSingle)
var lastSlash = path.lastIndexOf("/")
if(lastSlash < 0) return baseScheme + given
if((lastSlash >= 0)
&& (lastSlash < (path.length - 1)))
path = path.slice(0, lastSlash + 1) // Chop trailing filename from 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(/\/\.$/, '/')
return base.slice(0, baseSingle) + path
}
var tIOService;
if (typeof( isExtension ) != "undefined" && isExtension) {
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;
}
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);
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) {
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)) {
var k = uri.indexOf('//');
if (k<0) k=-2; // no host
var l = uri.indexOf('/', k+2); // First *single* slash
if (uri.slice(l+1, l+2) != '/' && base.slice(l+1, l+2) != '/'
&& uri.slice(0,l) == base.slice(0,l)) // common path to single slash
return uri.slice(l); // but no other common path segments
}
// fragment of base?
if (uri.slice(i, i+1) == '#' && base.length == i) return uri.slice(i);
while (i>0 && uri[i-1] != '/') i--;
$rdf.Util.uri.commonHost = new RegExp("^[-_a-zA-Z0-9.]+:(//[^/]*)?/[^/]*$");
if (i<3) return uri; // No way
if ((base.indexOf('//', i-2) > 0) || uri.indexOf('//', i-2) > 0)
return uri; // an unshared '//'
if (base.indexOf(':', i) >0) return uri; // unshared ':'
var n = 0;
for (var j=i; j<base.length; j++) if (base[j]=='/') n++;
if (n==0 && i < uri.length && uri[i] =='#') return './' + uri.slice(i);
if (n==0 && i == uri.length) return './';
var str = '';
for (var j=0; j<n; j++) str+= '../';
return str + uri.slice(i);
$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($rdf.Util.uri.commonHost)) {
var k = uri.indexOf('//');
if(k < 0) k = -2; // no host
var l = uri.indexOf('/', k + 2); // First *single* slash
if(uri.slice(l + 1, l + 2) != '/'
&& base.slice(l + 1, l + 2) != '/'
&& uri.slice(0, l) == base.slice(0, l))
// common path to single slash
return uri.slice(l); // but no other common path segments
}
// fragment of base?
if(uri.slice(i, i + 1) == '#' && base.length == i) return uri.slice(i);
while(i > 0 && uri[i - 1] != '/') i--;
if(i < 3) return uri; // No way
if((base.indexOf('//', i - 2) > 0)
|| uri.indexOf('//', i - 2) > 0)
return uri; // an unshared '//'
if(base.indexOf(':', i) > 0) return uri; // unshared ':'
var n = 0;
for(var j = i; j < base.length; j++) if(base[j] == '/') n++;
if(n == 0 && i < uri.length && uri[i] == '#') return './' + uri.slice(i);
if(n == 0 && i == uri.length) return './';
var str = '';
for(var j = 0; j < n; j++) str += '../';
return str + uri.slice(i);
}
/** returns URI without the frag **/
Util.uri.docpart = function (uri) {
var i = uri.indexOf("#")
if (i < 0) return uri
return uri.slice(0,i)
}
$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) {
var index = uri.indexOf(':');
if (index >= 0)
return uri.slice(0, index);
else
return null;
$rdf.Util.uri.protocol = function (uri) {
var index = uri.indexOf(':');
if(index >= 0) return uri.slice(0, index);
else return null;
} //protocol
URIjoin = Util.uri.join
uri_docpart = Util.uri.docpart
uri_protocol = Util.uri.protocol
//ends
//ends

View file

@ -2151,7 +2151,7 @@ Zotero.Translate.IO.String.prototype = {
"_initRDF":function(callback) {
Zotero.debug("Translate: Initializing RDF data store");
this._dataStore = new Zotero.RDF.AJAW.RDFIndexedFormula();
this._dataStore = new Zotero.RDF.AJAW.IndexedFormula();
this.RDF = new Zotero.Translate.IO._RDFSandbox(this._dataStore);
if(this.contentLength) {
@ -2262,9 +2262,9 @@ Zotero.Translate.IO.String.prototype = {
/**
* @class An API for handling RDF from the sandbox. This is exposed to translators as Zotero.RDF.
*
* @property {Zotero.RDF.AJAW.RDFIndexedFormula} _dataStore
* @property {Zotero.RDF.AJAW.IndexedFormula} _dataStore
* @property {Integer[]} _containerCounts
* @param {Zotero.RDF.AJAW.RDFIndexedFormula} dataStore
* @param {Zotero.RDF.AJAW.IndexedFormula} dataStore
*/
Zotero.Translate.IO._RDFSandbox = function(dataStore) {
this._dataStore = dataStore;
@ -2289,12 +2289,12 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
},
/**
* Gets a resource as a Zotero.RDF.AJAW.RDFSymbol, rather than a string
* @param {String|Zotero.RDF.AJAW.RDFSymbol} about
* @return {Zotero.RDF.AJAW.RDFSymbol}
* Gets a resource as a Zotero.RDF.AJAW.Symbol, rather than a string
* @param {String|Zotero.RDF.AJAW.Symbol} about
* @return {Zotero.RDF.AJAW.Symbol}
*/
"_getResource":function(about) {
return (typeof about == "object" ? about : new Zotero.RDF.AJAW.RDFSymbol(about));
return (typeof about == "object" ? about : new Zotero.RDF.AJAW.Symbol(about));
},
/**
@ -2311,7 +2311,7 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
* Serializes the current RDF to a string
*/
"serialize":function(dataMode) {
var serializer = Serializer();
var serializer = Zotero.RDF.AJAW.Serializer(this._dataStore);
for(var prefix in this._dataStore.namespaces) {
serializer.suggestPrefix(prefix, this._dataStore.namespaces[prefix]);
@ -2327,9 +2327,9 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
/**
* Adds an RDF triple
* @param {String|Zotero.RDF.AJAW.RDFSymbol} about
* @param {String|Zotero.RDF.AJAW.RDFSymbol} relation
* @param {String|Zotero.RDF.AJAW.RDFSymbol} value
* @param {String|Zotero.RDF.AJAW.Symbol} about
* @param {String|Zotero.RDF.AJAW.Symbol} relation
* @param {String|Zotero.RDF.AJAW.Symbol} value
* @param {Boolean} literal Whether value should be treated as a literal (true) or a resource
* (false)
*/
@ -2356,16 +2356,16 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
/**
* Creates a new anonymous resource
* @return {Zotero.RDF.AJAW.RDFSymbol}
* @return {Zotero.RDF.AJAW.Symbol}
*/
"newResource":function() {
return new Zotero.RDF.AJAW.RDFBlankNode();
return new Zotero.RDF.AJAW.BlankNode();
},
/**
* Creates a new container resource
* @param {String} type The type of the container ("bag", "seq", or "alt")
* @param {String|Zotero.RDF.AJAW.RDFSymbol} about The URI of the resource
* @param {String|Zotero.RDF.AJAW.Symbol} about The URI of the resource
* @return {Zotero.Translate.RDF.prototype.newContainer
*/
"newContainer":function(type, about) {
@ -2386,8 +2386,8 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
/**
* Adds a new element to a container
* @param {String|Zotero.RDF.AJAW.RDFSymbol} about The container
* @param {String|Zotero.RDF.AJAW.RDFSymbol} element The element to add to the container
* @param {String|Zotero.RDF.AJAW.Symbol} about The container
* @param {String|Zotero.RDF.AJAW.Symbol} element The element to add to the container
* @param {Boolean} literal Whether element should be treated as a literal (true) or a resource
* (false)
*/
@ -2395,13 +2395,13 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
const rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
var about = this._getResource(about);
this._dataStore.add(about, new Zotero.RDF.AJAW.RDFSymbol(rdf+"_"+(this._containerCounts[about.toNT()]++)), element, literal);
this._dataStore.add(about, new Zotero.RDF.AJAW.Symbol(rdf+"_"+(this._containerCounts[about.toNT()]++)), element, literal);
},
/**
* Gets all elements within a container
* @param {String|Zotero.RDF.AJAW.RDFSymbol} about The container
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
* @param {String|Zotero.RDF.AJAW.Symbol} about The container
* @return {Zotero.RDF.AJAW.Symbol[]}
*/
"getContainerElements":function(about) {
const liPrefix = "http://www.w3.org/1999/02/22-rdf-syntax-ns#_";
@ -2439,7 +2439,7 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
/**
* Gets the URI a specific resource
* @param {String|Zotero.RDF.AJAW.RDFSymbol} resource
* @param {String|Zotero.RDF.AJAW.Symbol} resource
* @return {String}
*/
"getResourceURI":function(resource) {
@ -2451,7 +2451,7 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
/**
* Gets all resources in the RDF data store
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
* @return {Zotero.RDF.AJAW.Symbol[]}
*/
"getAllResources":function() {
var returnArray = [];
@ -2463,7 +2463,7 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
/**
* Gets all arcs (predicates) into a resource
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
* @return {Zotero.RDF.AJAW.Symbol[]}
* @deprecated Since 2.1. Use {@link Zotero.Translate.IO["rdf"]._RDFBase#getStatementsMatching}
*/
"getArcsIn":function(resource) {
@ -2479,7 +2479,7 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
/**
* Gets all arcs (predicates) out of a resource
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
* @return {Zotero.RDF.AJAW.Symbol[]}
* @deprecated Since 2.1. Use {@link Zotero.Translate.IO["rdf"]._RDFBase#getStatementsMatching}
*/
"getArcsOut":function(resource) {
@ -2495,9 +2495,9 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
/**
* Gets all subjects whose predicates point to a resource
* @param {String|Zotero.RDF.AJAW.RDFSymbol} resource Subject that predicates should point to
* @param {String|Zotero.RDF.AJAW.RDFSymbol} property Predicate
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
* @param {String|Zotero.RDF.AJAW.Symbol} resource Subject that predicates should point to
* @param {String|Zotero.RDF.AJAW.Symbol} property Predicate
* @return {Zotero.RDF.AJAW.Symbol[]}
* @deprecated Since 2.1. Use {@link Zotero.Translate.IO["rdf"]._RDFBase#getStatementsMatching}
*/
"getSources":function(resource, property) {
@ -2513,9 +2513,9 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
/**
* Gets all objects of a given subject with a given predicate
* @param {String|Zotero.RDF.AJAW.RDFSymbol} resource Subject
* @param {String|Zotero.RDF.AJAW.RDFSymbol} property Predicate
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
* @param {String|Zotero.RDF.AJAW.Symbol} resource Subject
* @param {String|Zotero.RDF.AJAW.Symbol} property Predicate
* @return {Zotero.RDF.AJAW.Symbol[]}
* @deprecated Since 2.1. Use {@link Zotero.Translate.IO["rdf"]._RDFBase#getStatementsMatching}
*/
"getTargets":function(resource, property) {
@ -2532,9 +2532,9 @@ Zotero.Translate.IO._RDFSandbox.prototype = {
/**
* Gets statements matching a certain pattern
*
* @param {String|Zotero.RDF.AJAW.RDFSymbol} subj Subject
* @param {String|Zotero.RDF.AJAW.RDFSymbol} predicate Predicate
* @param {String|Zotero.RDF.AJAW.RDFSymbol} obj Object
* @param {String|Zotero.RDF.AJAW.Symbol} subj Subject
* @param {String|Zotero.RDF.AJAW.Symbol} predicate Predicate
* @param {String|Zotero.RDF.AJAW.Symbol} obj Object
* @param {Boolean} objLiteral Whether the object is a literal (as
* opposed to a URI)
* @param {Boolean} justOne Whether to stop when a single result is

View file

@ -419,7 +419,7 @@ Zotero.Translate.IO.Read.prototype = {
var baseURI = fileHandler.getURLSpecFromFile(this.file);
Zotero.debug("Translate: Initializing RDF data store");
this._dataStore = new Zotero.RDF.AJAW.RDFIndexedFormula();
this._dataStore = new Zotero.RDF.AJAW.IndexedFormula();
var parser = new Zotero.RDF.AJAW.RDFParser(this._dataStore);
try {
var nodes = Zotero.Translate.IO.parseDOMXML(this._rawStream, this._charset, this.file.fileSize);
@ -521,7 +521,7 @@ Zotero.Translate.IO.Write.prototype = {
"_initRDF":function() {
Zotero.debug("Translate: Initializing RDF data store");
this._dataStore = new Zotero.RDF.AJAW.RDFIndexedFormula();
this._dataStore = new Zotero.RDF.AJAW.IndexedFormula();
this.RDF = new Zotero.Translate.IO._RDFSandbox(this._dataStore);
},

View file

@ -234,14 +234,14 @@ function makeZoteroContext(isConnector) {
// Load RDF files into Zotero.RDF.AJAW namespace (easier than modifying all of the references)
const rdfXpcomFiles = [
'rdf/init',
'rdf/uri',
'rdf/term',
'rdf/identity',
'rdf/match',
'rdf/n3parser',
'rdf/rdfparser',
'rdf/serialize',
'rdf'
'rdf/serialize'
];
zContext.Zotero.RDF = {AJAW:{Zotero:zContext.Zotero}};
for (var i=0; i<rdfXpcomFiles.length; i++) {