mas01mj@640: /** mas01mj@640: * jOWL - a jQuery plugin for traversing and visualizing OWL-DL documents. mas01mj@640: * Creator - David Decraene mas01mj@640: * Version 1.0 mas01mj@640: * Website: mas01mj@640: * http://Ontologyonline.org mas01mj@640: * Licensed under the MIT license mas01mj@640: * http://www.opensource.org/licenses/mit-license.php mas01mj@640: * Verified with JSLint mas01mj@640: * http://www.jslint.com/ mas01mj@640: */ mas01mj@640: mas01mj@640: jOWL = window.jOWL = function( resource, options ){ return jOWL.getResource( resource, options ); }; mas01mj@640: jOWL.version = "1.0"; mas01mj@640: mas01mj@640: /** for debugging compatibility */ mas01mj@640: try { console.log('...'); } catch(e) { console = window.console = { log: function() {} } } mas01mj@640: if ($.browser.opera && opera.postError) { console = window.console = { log : function(){opera.postError(arguments); } }; } mas01mj@640: mas01mj@640: mas01mj@640: mas01mj@640: (function($){ mas01mj@640: mas01mj@640: /** mas01mj@640: * if no param: @return string of main namespaces mas01mj@640: * if 1 param: assume a documentElement, parse namespaces mas01mj@640: * if prefix & URI: Bind prefix to namespace URI mas01mj@640: */ mas01mj@640: jOWL.NS = function(prefix, URI){ mas01mj@640: if(!arguments.length) mas01mj@640: { return "xmlns:"+jOWL.NS.owl.prefix+"='"+jOWL.NS.owl()+"' xmlns:"+jOWL.NS.rdf.prefix+"='"+jOWL.NS.rdf()+"' xmlns:"+jOWL.NS.rdfs.prefix+"='"+jOWL.NS.rdfs()+"' xmlns:"+jOWL.NS.xsd.prefix+" ='"+jOWL.NS.xsd()+"'";} mas01mj@640: mas01mj@640: if(arguments.length == 1){ mas01mj@640: var attr = prefix.get(0).attributes; mas01mj@640: for(var i=0;i 0 ){ return xItems[0];} else { return null;} mas01mj@640: }; mas01mj@640: Element.prototype.selectSingleNode = function(cXPathString){ mas01mj@640: if(this.ownerDocument.selectSingleNode) { return this.ownerDocument.selectSingleNode(cXPathString, this);} mas01mj@640: else{throw "For XML Elements Only";} mas01mj@640: }; mas01mj@640: } mas01mj@640: mas01mj@640: /** @return A jQuery array of xml elements */ mas01mj@640: jOWL.Xpath = function(selector, elem){ mas01mj@640: var node = null; mas01mj@640: if(elem){ if(elem.each){ node = elem.get(0);} else { node = elem;} } mas01mj@640: var arr = node ? node.selectNodes(selector) : jOWL.document.selectNodes(selector); mas01mj@640: if($.browser.msie){ return $($.makeArray(arr));} return $(arr); //this is needed for IE, it returns a length of 1 on empty node array mas01mj@640: }; mas01mj@640: mas01mj@640: /** @return a String array of class references */ mas01mj@640: jOWL.Xpath.classes = function(jnode){ mas01mj@640: var cl = []; mas01mj@640: jOWL.Xpath(__.rdfs("subClassOf"), jnode) mas01mj@640: .each(function(){ mas01mj@640: var res = $(this).RDF_Resource(); mas01mj@640: if(res){ cl.push(res);} mas01mj@640: }); mas01mj@640: mas01mj@640: jOWL.Xpath(__.owl("intersectionOf")+"/"+__.owl("Class"), jnode) mas01mj@640: .each(function(){ mas01mj@640: var p = $(this).RDF_About(); if(p){ cl.push(p);} mas01mj@640: }); mas01mj@640: return cl; mas01mj@640: }; mas01mj@640: mas01mj@640: /** Functions stored in jOWL.priv are intended for local access only, to avoid a closure function */ mas01mj@640: jOWL.priv = { mas01mj@640: /** Arrray functions */ mas01mj@640: Array : { mas01mj@640: isArray : function(array){ mas01mj@640: return Object.prototype.toString.call(array) === '[object Array]'; mas01mj@640: }, mas01mj@640: pushUnique : function(array, item){ mas01mj@640: if(jOWL.priv.Array.getIndex(array, item) === -1){ array.push(item); return true;} mas01mj@640: return false; mas01mj@640: }, mas01mj@640: getIndex : function(array, item){ mas01mj@640: for (var i=0; i 0){ targetMatch = true;} mas01mj@640: } mas01mj@640: } mas01mj@640: else if(restriction.property.isDatatypeProperty){ mas01mj@640: targetMatch = restriction.property.assert(restriction.target, target); mas01mj@640: } mas01mj@640: else { targetMatch = (target == restriction.target);} mas01mj@640: } mas01mj@640: if(propertyMatch && targetMatch){ results.pushUnique(restriction);} mas01mj@640: mas01mj@640: }); mas01mj@640: if(options.inherited){ mas01mj@640: var clRestrictions = this.owlClass().sourceof(property, target, options) mas01mj@640: .each(function(){ mas01mj@640: //target can be a class, null, a duplicate individual... mas01mj@640: var clRestr = this; mas01mj@640: if(options.valuesOnly && clRestr.target === null){return;} mas01mj@640: var clTarget = this.getTarget(); mas01mj@640: if(clTarget.isClass && options.ignoreClasses){ return;} mas01mj@640: mas01mj@640: var containsProperty = false; mas01mj@640: for(var i = 0;i 0;} }); mas01mj@640: jOWL.Ontology.Datatype(__.xsd()+"decimal", {base: __.xsd()+"integer" }); mas01mj@640: jOWL.Ontology.Datatype(__.xsd()+"float", {base: __.xsd()+"integer" }); mas01mj@640: jOWL.Ontology.Datatype(__.xsd()+"double", {base: __.xsd()+"integer" }); mas01mj@640: jOWL.Ontology.Datatype(__.xsd()+"negativeInteger", {base: __.xsd()+"integer", assert : function(x){ return x < 0;} }); mas01mj@640: jOWL.Ontology.Datatype(__.xsd()+"nonNegativeInteger", {base: __.xsd()+"integer", assert : function(x){ return x >= 0;} }); mas01mj@640: jOWL.Ontology.Datatype(__.xsd()+"nonPositiveInteger", {base: __.xsd()+"integer", assert : function(x){ return x <= 0;} }); mas01mj@640: jOWL.Ontology.Datatype(__.xsd()+"string"); mas01mj@640: mas01mj@640: var URIPattern = /^([a-z0-9+.\-]+):(?:\/\/(?:((?:[a-z0-9-._~!$&'()*+,;=:]|%[0-9A-F]{2})*)@)?((?:[a-z0-9-._~!$&'()*+,;=]|%[0-9A-F]{2})*)(?::(\d*))?(\/(?:[a-z0-9-._~!$&'()*+,;=:@\/]|%[0-9A-F]{2})*)?|(\/?(?:[a-z0-9-._~!$&'()*+,;=:@]|%[0-9A-F]{2})+(?:[a-z0-9-._~!$&'()*+,;=:@\/]|%[0-9A-F]{2})*)?)(?:\?((?:[a-z0-9-._~!$&'()*+,;=:\/?@]|%[0-9A-F]{2})*))?(?:#((?:[a-z0-9-._~!$&'()*+,;=:\/?@]|%[0-9A-F]{2})*))?$/i; mas01mj@640: mas01mj@640: jOWL.Ontology.Datatype(__.xsd()+"anyURI", {base: __.xsd()+"string", pattern : URIPattern }); mas01mj@640: jOWL.Ontology.Datatype(__.xsd()+"boolean", {sanitize : function(x){ mas01mj@640: if(typeof x == 'boolean'){ return x;} mas01mj@640: if(x == 'true'){ return true;} mas01mj@640: if(x == 'false'){ return false;} mas01mj@640: }, assert : function(x){ mas01mj@640: return typeof x == 'boolean'; mas01mj@640: }, match: function(a, b){ mas01mj@640: if(a === "false"){ a = false;} mas01mj@640: if(a === "true"){ a = true;} mas01mj@640: return (a === b); mas01mj@640: }}); mas01mj@640: mas01mj@640: /** 'superclass' for Properties */ mas01mj@640: jOWL.Ontology.Property = function(jnode){ mas01mj@640: var r = this.parseProperty(jnode); mas01mj@640: if(r){ return r;} mas01mj@640: }; mas01mj@640: mas01mj@640: jOWL.Ontology.Property.prototype = $.extend({}, jOWL.Ontology.Thing.prototype,{ mas01mj@640: isProperty : true, mas01mj@640: parseProperty : function(jnode){ mas01mj@640: if(!jnode || typeof jnode == 'string'){ mas01mj@640: this.domain = this.range = null; mas01mj@640: this.parse(jnode); mas01mj@640: return; mas01mj@640: } mas01mj@640: if(jOWL.options.cacheProperties && jOWL.indices.IDs){ mas01mj@640: var res = jnode.RDF_ID() || jnode.RDF_About(); mas01mj@640: var c = jOWL.index('property').get(res); mas01mj@640: if(c){ return c;} mas01mj@640: } mas01mj@640: this.parse(jnode); mas01mj@640: this.domain= $(this.jnode.get(0).selectSingleNode(__.rdfs('domain'))).RDF_Resource(); mas01mj@640: this.range = $(this.jnode.get(0).selectSingleNode(__.rdfs('range'))).RDF_Resource(); mas01mj@640: } mas01mj@640: }); mas01mj@640: mas01mj@640: /** access to Datatype properties */ mas01mj@640: jOWL.Ontology.DatatypeProperty = function(jnode){ mas01mj@640: var r = this.parseProperty(jnode); mas01mj@640: if(r){ return r;} mas01mj@640: if(this.type == __.owl("AnnotationProperty")){ this.range = __.xsd()+"string";} mas01mj@640: }; mas01mj@640: mas01mj@640: jOWL.Ontology.DatatypeProperty.prototype = $.extend({}, jOWL.Ontology.Thing.prototype, jOWL.Ontology.Property.prototype, { mas01mj@640: isDatatypeProperty : true, mas01mj@640: /** check datatype values against this */ mas01mj@640: assert : function(targetValue, value){ mas01mj@640: var self = this; mas01mj@640: var dt = jOWL.Ontology.Datatype[this.range]; mas01mj@640: if(!dt){ mas01mj@640: console.log(this.range+" datatype reasoning not implemented"); mas01mj@640: return true; mas01mj@640: } mas01mj@640: if(value === undefined){ return dt.assert(targetValue);} mas01mj@640: else {return dt.match(value, targetValue);} mas01mj@640: } mas01mj@640: }); mas01mj@640: mas01mj@640: /** access to Object properties */ mas01mj@640: jOWL.Ontology.ObjectProperty = function(jnode){ mas01mj@640: var r = this.parseProperty(jnode); mas01mj@640: if(r){ return r;} mas01mj@640: var self = this; mas01mj@640: jOWL.Xpath(__.rdf('type'), this.jnode).each(function(){ mas01mj@640: if($(this).RDF_Resource() == __.owl()+"TransitiveProperty"){ self.isTransitive = true;} mas01mj@640: }); mas01mj@640: if(this.jnode.get(0).nodeName == __.owl("TransitiveProperty")){ self.isTransitive = true;} mas01mj@640: }; mas01mj@640: mas01mj@640: jOWL.Ontology.ObjectProperty.prototype = $.extend({}, jOWL.Ontology.Thing.prototype, jOWL.Ontology.Property.prototype, { mas01mj@640: isObjectProperty : true mas01mj@640: }); mas01mj@640: mas01mj@640: /** access to an owl:Class */ mas01mj@640: jOWL.Ontology.Class = function(jnode){ mas01mj@640: this.parse(jnode); mas01mj@640: }; mas01mj@640: mas01mj@640: /** @return jOWL Array of Restrictions */ mas01mj@640: jOWL.Xpath.restrictions = function(jnode){ mas01mj@640: var result = new jOWL.Ontology.Array(); mas01mj@640: jOWL.Xpath(__.rdfs("subClassOf")+"/"+__.owl("Restriction"), jnode) mas01mj@640: .add(jOWL.Xpath(__.owl("intersectionOf")+"/"+__.owl("Restriction"), jnode)) mas01mj@640: .each(function(){ mas01mj@640: result.push(new jOWL.Ontology.Restriction($(this))); mas01mj@640: }); mas01mj@640: return result; mas01mj@640: }; mas01mj@640: mas01mj@640: /** Internal Use */ mas01mj@640: jOWL.Ontology.Intersection = function(jnode){ mas01mj@640: var self = this; mas01mj@640: this.jnode = jnode; mas01mj@640: this._arr = []; mas01mj@640: this.URI = this.jnode.parent().RDF_ID(); mas01mj@640: this.matches = {}; mas01mj@640: jOWL.Xpath(__.owl("Restriction"), jnode).each(function(){ mas01mj@640: var restr = new jOWL.Ontology.Restriction($(this)); mas01mj@640: if(restr.isValueRestriction){self._arr.push(restr);} mas01mj@640: }); mas01mj@640: jOWL.Xpath(__.owl('Class'), jnode).each(function(){ mas01mj@640: var uri = $(this).RDF_About(); mas01mj@640: if(uri){ self._arr.push(jOWL(uri));} mas01mj@640: }); mas01mj@640: }; mas01mj@640: mas01mj@640: jOWL.Ontology.Intersection.prototype = { mas01mj@640: isIntersection : true, mas01mj@640: jOWL : jOWL.version, mas01mj@640: match : function(id, cls, clRestr){ mas01mj@640: if(id == this.URI){ return false;} mas01mj@640: if(this.matches[id] !== undefined){ return this.matches[id]; }//local cache mas01mj@640: mas01mj@640: for(var i =0;i 1){ oParents.filter(function(){return this.name != ('Thing');});} //Remove Thing reference if other parents exist mas01mj@640: jOWL.data(this.name, "parents", oParents); mas01mj@640: return oParents; mas01mj@640: }, mas01mj@640: /** @return ancestors to the class in a jOWL.Ontology.Array */ mas01mj@640: ancestors : function(){ mas01mj@640: return this.hierarchy(false).flatindex; mas01mj@640: }, mas01mj@640: /** mas01mj@640: Constructs the entire (parent) hierarchy for a class mas01mj@640: @return a jOWL.Ontology.Array containing top nodes (classes directly subsumed by 'owl:Thing') mas01mj@640: @param addInverse add a variable invParents (jOWL.Ontology.Array of child references) to each node with exception of the leaves (original concept) mas01mj@640: */ mas01mj@640: hierarchy : function(addInverse){ mas01mj@640: var endNodes = new jOWL.Ontology.Array(); mas01mj@640: var self = this; mas01mj@640: endNodes.flatindex = new jOWL.Ontology.Array(); mas01mj@640: mas01mj@640: function URIARR(p_arr, obj){ mas01mj@640: var add = true; mas01mj@640: if(!obj){ obj = {}; add = false;} mas01mj@640: if(p_arr.each){ mas01mj@640: p_arr.each(function(){ mas01mj@640: if(obj[this.URI]){return;} mas01mj@640: if(this.URI == __.owl()+'Thing'){ return;} mas01mj@640: if(add){ obj[this.URI] = true;} mas01mj@640: if(this.parents){ URIARR(this.parents(), obj);} mas01mj@640: }); mas01mj@640: } mas01mj@640: return obj; mas01mj@640: } mas01mj@640: mas01mj@640: function traverse(concept){ mas01mj@640: var parents = concept.parents(); mas01mj@640: if(parents.length == 1 && parents.contains(__.owl()+'Thing')){ endNodes.pushUnique(concept); return;} mas01mj@640: else mas01mj@640: { mas01mj@640: var asso = jOWL.options.reason ? URIARR(parents) : {}; mas01mj@640: parents.filter(function(){ return (!asso[this.URI]);}); //throw out redundancies mas01mj@640: parents.each(function(){ mas01mj@640: var item = endNodes.flatindex.pushUnique(this); mas01mj@640: if(addInverse){ mas01mj@640: if(!item.invParents){ item.invParents = new jOWL.Ontology.Array();} mas01mj@640: item.invParents.pushUnique(concept); mas01mj@640: } mas01mj@640: traverse(item); mas01mj@640: }); mas01mj@640: concept.setParents(parents); mas01mj@640: } mas01mj@640: } mas01mj@640: mas01mj@640: traverse(this); mas01mj@640: return endNodes; mas01mj@640: mas01mj@640: }, mas01mj@640: /** mas01mj@640: @param level depth to fetch children, Default 5 mas01mj@640: @return jOWL array of classes that are descendant mas01mj@640: */ mas01mj@640: descendants : function(level){ mas01mj@640: level = (typeof level == 'number') ? level : 5; mas01mj@640: var oDescendants = jOWL.data(this.name, "descendants"); mas01mj@640: if(oDescendants && oDescendants.level >= level){ return oDescendants;} mas01mj@640: oDescendants = new jOWL.Ontology.Array(); mas01mj@640: oDescendants.level = level; mas01mj@640: mas01mj@640: function descend(concept, i){ mas01mj@640: if(i <= level){ mas01mj@640: i++; mas01mj@640: var ch = concept.children(); mas01mj@640: oDescendants.concat(ch); mas01mj@640: ch.each(function(item){ descend(item, i);}); mas01mj@640: } mas01mj@640: } mas01mj@640: mas01mj@640: descend(this, 1); mas01mj@640: jOWL.data(this.name, "descendants", oDescendants); mas01mj@640: return oDescendants; mas01mj@640: }, mas01mj@640: /** @return jOWL.Array of Restrictions, target is an individual, not a class or undefined (unless includeAll is specified) - deprecated */ mas01mj@640: valueRestrictions : function(includeAll, array){ mas01mj@640: return this.sourceof(null, null, {ignoreClasses : !includeAll}); mas01mj@640: }, mas01mj@640: /** mas01mj@640: get all restrictions that satisfy the arguments mas01mj@640: @param property property or array of properties, or null mas01mj@640: @param target class, individuals of array of them, or null mas01mj@640: @return jOWL.Array of Restrictions mas01mj@640: */ mas01mj@640: sourceof : function(property, target, options){ mas01mj@640: options = $.extend({ mas01mj@640: inherited : true, // add restrictions specified on parents as well mas01mj@640: transitive : true, //expand on transitive relations too mas01mj@640: ignoreGenerics : true, //if a parent has an identical property, with another target 'Thing', skip that restriction mas01mj@640: ignoreClasses : false, //only individuals should return mas01mj@640: valuesOnly : true //do not return valueless criteria mas01mj@640: }, options); mas01mj@640: var self = this; mas01mj@640: var crit = jOWL.data(this.name, "sourceof"); mas01mj@640: var jnode = this.jnode; mas01mj@640: mas01mj@640: if(!crit){ mas01mj@640: crit = new jOWL.Ontology.Array(); mas01mj@640: var arr = jOWL.Xpath(__.rdfs("subClassOf")+"/"+__.owl("Restriction"), jnode) mas01mj@640: .add(jOWL.Xpath(__.owl("intersectionOf")+"/"+__.owl("Restriction"), jnode)); mas01mj@640: arr.each(function(index, entry){ mas01mj@640: var cr = new jOWL.Ontology.Restriction($(entry)); mas01mj@640: var dupe = false; mas01mj@640: crit.each(function(item, i){ mas01mj@640: if(this.property.name == cr.property.name){ dupe = item;} mas01mj@640: }); mas01mj@640: if(dupe){ if(!dupe.merge(cr)){ crit.push(cr);} } mas01mj@640: else { crit.push(cr);} mas01mj@640: }); mas01mj@640: jOWL.data(self.name, "sourceof", crit); mas01mj@640: } mas01mj@640: var results = new jOWL.Ontology.Array(); mas01mj@640: mas01mj@640: crit.each(function(){ mas01mj@640: mas01mj@640: var propertyMatch = property ? false : true; mas01mj@640: var targetMatch = target ? false : true; mas01mj@640: mas01mj@640: if(!propertyMatch){ mas01mj@640: if(property.isArray){ propertyMatch = property.contains(this.property);} mas01mj@640: else { propertyMatch = (property.URI == this.property.URI);} mas01mj@640: } mas01mj@640: mas01mj@640: if(!target){ mas01mj@640: if(options.transitive && this.property.isTransitive){ mas01mj@640: var rTarget = this.getTarget(); mas01mj@640: var transitives = rTarget.sourceof(this.property, null, options); mas01mj@640: results.concat(transitives); mas01mj@640: } mas01mj@640: } mas01mj@640: mas01mj@640: if(!targetMatch && !this.target){ mas01mj@640: targetMatch = !options.valuesOnly; mas01mj@640: } mas01mj@640: mas01mj@640: if(!targetMatch){ mas01mj@640: var targ = this.getTarget(); mas01mj@640: if(targ.isClass && options.ignoreClasses){ return;} mas01mj@640: targetMatch = jOWL.priv.testObjectTarget(target, this.target); mas01mj@640: if(!targetMatch && options.transitive && propertyMatch && this.property.isTransitive){ mas01mj@640: if(targ.isThing){ mas01mj@640: if(targ.sourceof(property, target).length){ targetMatch = true;} mas01mj@640: } mas01mj@640: } mas01mj@640: } mas01mj@640: mas01mj@640: if(propertyMatch && targetMatch){ results.pushUnique(this);} mas01mj@640: }); mas01mj@640: mas01mj@640: if(!options.inherited){ return results;} mas01mj@640: mas01mj@640: this.parents().each(function(){ mas01mj@640: if(this.sourceof){ mas01mj@640: this.sourceof(property, target, options).each(function(parentsource){ mas01mj@640: var ptarget = this.getTarget(); mas01mj@640: var containsProperty = false; mas01mj@640: var tempArray = new jOWL.Ontology.Array(); mas01mj@640: results.filter(function(){ mas01mj@640: var restr = this, keep = true; mas01mj@640: if(restr.property.URI == parentsource.property.URI){ mas01mj@640: containsProperty = true; mas01mj@640: if(!options.ignoreGenerics){ mas01mj@640: if(parentsource.target != restr.target){ tempArray.push(parentsource);} mas01mj@640: } else { mas01mj@640: if(ptarget.isThing){ mas01mj@640: keep = restr.getTarget().isThing && parentsource.target != restr.target; mas01mj@640: tempArray.push(parentsource); mas01mj@640: } mas01mj@640: } mas01mj@640: } mas01mj@640: return keep; mas01mj@640: }); mas01mj@640: if(!containsProperty){ results.push(parentsource);} mas01mj@640: results.concat(tempArray); mas01mj@640: }); mas01mj@640: } mas01mj@640: }); mas01mj@640: return results; mas01mj@640: } mas01mj@640: }); mas01mj@640: mas01mj@640: /** Utility object */ mas01mj@640: jOWL.Ontology.Array = function(arr, isXML){ mas01mj@640: var self = this; mas01mj@640: this.items = []; mas01mj@640: if(arr){ mas01mj@640: if(isXML){ $.each(arr, function(){ mas01mj@640: var entry = this.jOWL ? this : jOWL($(this)); mas01mj@640: self.items.push(entry);}); mas01mj@640: } mas01mj@640: else { this.items = arr;} mas01mj@640: } mas01mj@640: this.length = this.items.length; mas01mj@640: }; mas01mj@640: mas01mj@640: jOWL.Ontology.Array.prototype = { mas01mj@640: jOWL : jOWL.version, mas01mj@640: isArray : true, mas01mj@640: bind : function(listitem, fn){ mas01mj@640: return this.map(function(){ mas01mj@640: var syntax = listitem ? listitem.clone(true) : $(''); mas01mj@640: var html = this.bind(syntax).append(document.createTextNode(' ')); mas01mj@640: if(fn){ fn.call(html, html, this);} mas01mj@640: return html.get(0); mas01mj@640: }); mas01mj@640: }, mas01mj@640: concat : function(arr, ignoreUnique){ mas01mj@640: var self = this; mas01mj@640: if(arr.each){ arr.each(function(){ mas01mj@640: if(ignoreUnique){ self.push(this); } mas01mj@640: else { self.pushUnique(this); } mas01mj@640: }); mas01mj@640: } mas01mj@640: else { self.items = self.items.concat(arr.items); this.length = self.items.length;} mas01mj@640: return this; mas01mj@640: }, mas01mj@640: contains : function(o){ mas01mj@640: return this.get(o) ? true: false; mas01mj@640: }, mas01mj@640: each : function(fn, reverse){ mas01mj@640: var i, self = this; mas01mj@640: var stop = false; mas01mj@640: if(reverse){ mas01mj@640: for(i=this.items.length - 1; i>=0;i--){ mas01mj@640: if(stop){ break;} mas01mj@640: (function(){ mas01mj@640: var item = self.eq(i); mas01mj@640: if(fn.call(item, item, i) === false){ stop = true;} mas01mj@640: })(); mas01mj@640: } mas01mj@640: } mas01mj@640: else { mas01mj@640: for(i=0;i this.items.length -1){ return null;} mas01mj@640: return this.items[index]; mas01mj@640: }, mas01mj@640: filter : function(fn){ mas01mj@640: var self = this; mas01mj@640: this.each(function(item, i){ mas01mj@640: var q = fn.call(item, item, i); mas01mj@640: if(!q){ self.items.splice(i, 1);} mas01mj@640: }, true); mas01mj@640: this.length = this.items.length; mas01mj@640: return this; mas01mj@640: }, mas01mj@640: getIndex : function(o){ mas01mj@640: var found = -1; mas01mj@640: if(o.equals){ mas01mj@640: this.each(function(a, i){ mas01mj@640: if(this.equals && this.equals(o)){ found = i; return false;} mas01mj@640: }); mas01mj@640: } mas01mj@640: else { mas01mj@640: if(typeof o == 'number'){ return o;} mas01mj@640: var name = typeof o == "string" ? o : o.name; mas01mj@640: var URI = o.URI || name; mas01mj@640: mas01mj@640: this.each(function(a, i){ mas01mj@640: if(this.URI){ if(this.URI == URI){ found = i;}} mas01mj@640: else if(this.name == name){ found = i;} mas01mj@640: }); mas01mj@640: } mas01mj@640: return found; mas01mj@640: }, mas01mj@640: get : function(o){ mas01mj@640: return this.eq(this.getIndex(o)); mas01mj@640: }, mas01mj@640: map : function(fn){ mas01mj@640: var arr = []; mas01mj@640: this.each(function(){ arr.push(fn.call(this, this));}); mas01mj@640: return arr; mas01mj@640: }, mas01mj@640: push : function(o){ mas01mj@640: this.items.push(o); mas01mj@640: this.length = this.items.length; mas01mj@640: return this; mas01mj@640: }, mas01mj@640: pushUnique : function(o){ mas01mj@640: return this.get(o) || this.push(o).get(o); mas01mj@640: }, mas01mj@640: toString : function(){ mas01mj@640: return this.map(function(){return this.URI;}).join(', '); mas01mj@640: }, mas01mj@640: /** Convert this array into an associative array with key = URI */ mas01mj@640: associative : function(){ mas01mj@640: var arr = {}; mas01mj@640: this.each(function(){ mas01mj@640: if(this.URI){ arr[this.URI] = this;} mas01mj@640: }); mas01mj@640: return arr; mas01mj@640: } mas01mj@640: }; mas01mj@640: mas01mj@640: mas01mj@640: jOWL.options = {reason: true, locale:false, defaultlocale: 'en', mas01mj@640: dictionary : { create: true, addID : true }, mas01mj@640: onParseError : function(msg){alert("jOWL parseError: "+msg);}, cacheProperties : true, niceClassLabels : true}; mas01mj@640: jOWL.document = null; mas01mj@640: jOWL.namespace = null; mas01mj@640: jOWL.indices = { //internal indices mas01mj@640: P : null, //jOWL array mas01mj@640: data : {}, mas01mj@640: IDs : null, mas01mj@640: I : null, //Intersection mas01mj@640: T : null, //Thing mas01mj@640: D : null, //dictionary mas01mj@640: reset : function(){var i = jOWL.indices; i.data = {}; i.P = null; i.T = null; i.IDs = null; i.I = null;i.D = null;} mas01mj@640: }; mas01mj@640: mas01mj@640: jOWL.index = function(type, wipe){ mas01mj@640: var i = jOWL.indices; mas01mj@640: switch (type) mas01mj@640: { mas01mj@640: /**jOWL indexes all elements with rdf:ID, and first order ontology elements specified with rdf:about mas01mj@640: @return Associative array with key = URI and value = jOWL object. mas01mj@640: */ mas01mj@640: case "ID": mas01mj@640: if(i.IDs === null || wipe){ mas01mj@640: if(wipe){ i.reset();} mas01mj@640: i.IDs = {}; mas01mj@640: i.T = {}; mas01mj@640: var start = new Date(); mas01mj@640: mas01mj@640: var rID = jOWL.Xpath("//*[@"+__.rdf("ID")+"]").each(function(){ mas01mj@640: var jowl = jOWL.getResource($(this)); mas01mj@640: if(jowl){ mas01mj@640: i.IDs[jowl.URI] = jowl; mas01mj@640: if(jowl.isThing){ mas01mj@640: if(!i.T[jowl.Class]){ i.T[jowl.Class] = new jOWL.Ontology.Array();} mas01mj@640: i.T[jowl.Class].push(jowl); mas01mj@640: } mas01mj@640: } mas01mj@640: }); mas01mj@640: mas01mj@640: var rAbout = jOWL.Xpath("/"+__.rdf("RDF")+"/*[@"+__.rdf("about")+"]").each(function(){ mas01mj@640: var jnode = $(this); mas01mj@640: var jowl = jOWL.getResource($(this)); mas01mj@640: if(!jowl){ return;} mas01mj@640: if(jowl.isClass || jowl.isProperty || jowl.isThing){ mas01mj@640: if(i.IDs[jowl.URI]){ jnode.children().appendTo(i.IDs[jowl.URI].jnode); return;} mas01mj@640: i.IDs[jowl.URI] = jowl; mas01mj@640: if(jowl.isThing){ mas01mj@640: if(!i.T[jowl.Class]){ i.T[jowl.Class] = new jOWL.Ontology.Array();} mas01mj@640: i.T[jowl.Class].push(jowl); mas01mj@640: } mas01mj@640: return; mas01mj@640: } mas01mj@640: }); mas01mj@640: console.log("Loaded in "+(new Date().getTime() - start.getTime())+"ms"); mas01mj@640: } mas01mj@640: return i.IDs; mas01mj@640: /** Generated together with ID index. mas01mj@640: * @return Associative Array, key = class, value = jOWL Array of individuals. mas01mj@640: */ mas01mj@640: case "Thing": mas01mj@640: return i.T; mas01mj@640: case "intersection": mas01mj@640: if(i.I === null || wipe){ mas01mj@640: var temp = new jOWL.Ontology.Array(); mas01mj@640: i.I = {}; mas01mj@640: jOWL.Xpath("//"+__.owl("intersectionOf")).each(function(){ mas01mj@640: var isect = new jOWL.Ontology.Intersection($(this)); mas01mj@640: if(!isect.URI){return;} mas01mj@640: var dupe = temp.get(isect); mas01mj@640: if(dupe){ mas01mj@640: console.log("duplicate intersection found between : (Ignoring) "+isect.URI+" and "+dupe.URI); mas01mj@640: } else { mas01mj@640: if(!i.I[isect.URI]){i.I[isect.URI] = new jOWL.Ontology.Array();} mas01mj@640: temp.push(isect); mas01mj@640: i.I[isect.URI].push(isect); mas01mj@640: } mas01mj@640: }); mas01mj@640: } mas01mj@640: return i.I; mas01mj@640: case "property": mas01mj@640: if(i.P === null || wipe) mas01mj@640: { mas01mj@640: jOWL.options.cacheProperties = false; mas01mj@640: i.P = new jOWL.Ontology.Array(); mas01mj@640: for(x in i.IDs){ mas01mj@640: var jowl = i.IDs[x]; mas01mj@640: if(jowl.isProperty){ i.P.push(jowl);} mas01mj@640: } mas01mj@640: jOWL.options.cacheProperties = true; mas01mj@640: } mas01mj@640: return i.P; mas01mj@640: case "dictionary": mas01mj@640: /**Dictionary: Array of Arrays, where secondary array is of form: [0] = term, [1] = rdfID, [2] = locale */ mas01mj@640: if(i.D === null || wipe) mas01mj@640: { mas01mj@640: i.D = []; mas01mj@640: for(x in i.IDs){ mas01mj@640: var entry = i.IDs[x]; mas01mj@640: i.D = i.D.concat(entry.terms()); mas01mj@640: } mas01mj@640: } mas01mj@640: return i.D; mas01mj@640: } mas01mj@640: }; mas01mj@640: mas01mj@640: /** Internal Function, storing data in associative array (JSON), mas01mj@640: jquery data function cannot be used as expando data does not work in IE for ActiveX XMLhttprequest*/ mas01mj@640: jOWL.data = function(rdfID, dtype, data){ mas01mj@640: var d = jOWL.indices.data; mas01mj@640: if(!d[rdfID]){ d[rdfID] = {};} mas01mj@640: if(!data){ return d[rdfID][dtype];} mas01mj@640: d[rdfID][dtype] = data; mas01mj@640: }; mas01mj@640: mas01mj@640: /** mas01mj@640: * Initialize jOWL with an OWL-RDFS document. mas01mj@640: * @param path relative path to xml document mas01mj@640: * @param callback callback function to be called when loaded. mas01mj@640: * @options : optional settings: mas01mj@640: * onParseError : function(msg){} function to ba called when parsing fails mas01mj@640: * reason : true/false, turns on additional reasoning at the expense of performance mas01mj@640: * locale: set preferred language (if available), examples en, fr... mas01mj@640: */ mas01mj@640: jOWL.load = function(path, callback, options){ mas01mj@640: var that = this; mas01mj@640: if($.browser.msie && location.toString().indexOf('file') === 0){ //IE won't load local xml files otherwise mas01mj@640: var xml = document.createElement("xml"); mas01mj@640: xml.validateOnParse = false; //IE throws DTD errors (for 'rdf:') on perfectly defined OWL files otherwise mas01mj@640: xml.src = path; mas01mj@640: xml.onreadystatechange = function(){ mas01mj@640: if(xml.readyState == "interactive"){ var xmldoc = xml.XMLDocument; document.body.removeChild(xml);callback(that.parse(xmldoc, options));} mas01mj@640: }; mas01mj@640: document.body.appendChild(xml); mas01mj@640: } mas01mj@640: else { mas01mj@640: $.get(path, function(xml){callback(that.parse(xml, options));}); mas01mj@640: } mas01mj@640: }; mas01mj@640: mas01mj@640: /** mas01mj@640: * initialize jOWL with some OWL-RDFS syntax mas01mj@640: * @param doc Either an xmlString or an xmlDocument mas01mj@640: * @param options optional, onParseError(msg) : function to execute when parse fails mas01mj@640: * @returns false on failure, or the jOWL object mas01mj@640: */ mas01mj@640: jOWL.parse = function(doc, options){ mas01mj@640: jOWL.document = null; mas01mj@640: this.options = $.extend(jOWL.options, options); mas01mj@640: if(typeof doc == 'string'){ doc = jOWL.fromString(doc);} mas01mj@640: jOWL.document = doc; mas01mj@640: if($.browser.msie){ mas01mj@640: if(doc.parseError.errorCode !== 0){ jOWL.options.onParseError(doc.parseError.reason); return false;} mas01mj@640: } mas01mj@640: else if(doc.documentElement.nodeName == 'parsererror'){jOWL.options.onParseError(doc.documentElement.firstChild.nodeValue); return false;} mas01mj@640: var root = $(doc.documentElement); mas01mj@640: jOWL.NS(root); mas01mj@640: if($.browser.msie){ mas01mj@640: jOWL.document.setProperty("SelectionLanguage", "XPath"); mas01mj@640: jOWL.document.setProperty("SelectionNamespaces", __()); mas01mj@640: } mas01mj@640: this.index('ID', true); mas01mj@640: if(jOWL.options.cacheProperties){ this.index('property', true);} mas01mj@640: if(jOWL.options.dictionary.create){ jOWL.index("dictionary");} mas01mj@640: jOWL.Thing = new jOWL.Ontology.Thing($(jOWL.create(__.owl, "Class").attr(__.rdf, 'about', __.owl()+'Thing').node)); mas01mj@640: jOWL.Thing.type = false; mas01mj@640: return this; mas01mj@640: }; mas01mj@640: mas01mj@640: /** mas01mj@640: * A String representation of the OWL-RDFS document mas01mj@640: * @param xmlNode optional, node to generate a string from, when unspecified the entire document mas01mj@640: */ mas01mj@640: jOWL.toString = function(xmlNode){ mas01mj@640: if(!xmlNode){ return jOWL.toString(jOWL.document);} mas01mj@640: if($.browser.msie){ return xmlNode.xml;} mas01mj@640: return new XMLSerializer().serializeToString(xmlNode);// Gecko-based browsers, Safari, Opera. mas01mj@640: }; mas01mj@640: mas01mj@640: /** create a document from string */ mas01mj@640: jOWL.fromString = function(doc){ mas01mj@640: var owldoc; mas01mj@640: if(document.implementation.createDocument){ owldoc = new DOMParser().parseFromString(doc, "text/xml");} // Mozilla and Netscape browsers mas01mj@640: else if(window.ActiveXObject){ // MSIE mas01mj@640: var xmldoc = new ActiveXObject("Microsoft.XMLDOM"); mas01mj@640: xmldoc.async="false"; mas01mj@640: xmldoc.validateOnParse = false; mas01mj@640: xmldoc.loadXML(doc); mas01mj@640: owldoc = xmldoc; mas01mj@640: } mas01mj@640: return owldoc; mas01mj@640: }; mas01mj@640: mas01mj@640: /** @return false if belongs to this namespace, or an array with length two, arr[0] == url, arr[1] == id */ mas01mj@640: jOWL.isExternal = function(resource){ mas01mj@640: var r = jOWL.resolveURI(resource, true); mas01mj@640: return r[0] != jOWL.namespace ? r : false; mas01mj@640: }; mas01mj@640: mas01mj@640: /** mas01mj@640: if a URI belongs to the loaded namespace, then strips the prefix url of, else preserves URI mas01mj@640: also able to parse and reference html (or jquery) elements for their URI. mas01mj@640: */ mas01mj@640: jOWL.resolveURI = function(URI, array){ mas01mj@640: if(typeof URI != "string"){ mas01mj@640: var node = URI.jquery ? URI.get(0) : URI; mas01mj@640: URI = node.localName || node.baseName; mas01mj@640: if(node.namespaceURI){ URI = node.namespaceURI + URI;} mas01mj@640: return jOWL.resolveURI(URI, array); mas01mj@640: } mas01mj@640: var rs = URI, ns = jOWL.namespace; mas01mj@640: if(URI.indexOf('http') === 0){ mas01mj@640: var tr = URI.indexOf('#'); mas01mj@640: if(tr <= 0){ tr = URI.lastIndexOf('/');} mas01mj@640: if(tr > 0) mas01mj@640: { mas01mj@640: ns = URI.substring(0, tr+1); mas01mj@640: rs = URI.substring(tr+1); mas01mj@640: } mas01mj@640: } else if(URI.charAt(0) == '#'){ return URI.substring(1);} mas01mj@640: if(array){ return [ns, rs];} mas01mj@640: if(ns == jOWL.namespace){ return rs;} mas01mj@640: return URI; mas01mj@640: }; mas01mj@640: mas01mj@640: /** mas01mj@640: Main method to get an Ontology Object, access via jOWL(>String>, options); mas01mj@640: resource: rdfID/rdfResource or jQuery node. mas01mj@640: */ mas01mj@640: jOWL.getResource = function(resource, options){ mas01mj@640: if(!jOWL.document){ throw "You must successfully load an ontology before you can find anything";} mas01mj@640: if(!resource){ throw "No resource specified";} mas01mj@640: var node; mas01mj@640: var opts = $.extend({}, options); mas01mj@640: if(typeof resource == 'string'){ mas01mj@640: resource = jOWL.resolveURI(resource); mas01mj@640: if(resource == 'Thing' || resource == __.owl()+'Thing'){ return jOWL.Thing;} mas01mj@640: if(opts.type == 'property' && jOWL.options.cacheProperties){ mas01mj@640: var c = jOWL.index('property').get(resource); mas01mj@640: if(c){ return c;} mas01mj@640: if(jOWL.isExternal(resource)){ console.log("undeclared resource: "+resource); return new jOWL.Ontology.Property(resource);} mas01mj@640: } mas01mj@640: var match = jOWL.index("ID")[resource]; mas01mj@640: if(!match){ //try case insensitive mas01mj@640: for(caseIns in jOWL.index("ID")){ mas01mj@640: if(caseIns.toLowerCase() == resource.replace(/ /g, "").toLowerCase()){ match = jOWL.index("ID")[caseIns]; break;} mas01mj@640: } mas01mj@640: } mas01mj@640: if(!match){ mas01mj@640: if(jOWL.isExternal(resource)){ mas01mj@640: console.log("undeclared resource: "+resource); mas01mj@640: return new jOWL.Ontology.Thing(resource); mas01mj@640: } mas01mj@640: console.log(resource+" not found"); mas01mj@640: return null; mas01mj@640: } mas01mj@640: return match; mas01mj@640: } mas01mj@640: node = resource.jquery ? resource : $(resource); mas01mj@640: var jj = jOWL.type(node); if(!jj){ return null;} mas01mj@640: return new (jj)(node); mas01mj@640: }; mas01mj@640: mas01mj@640: /** mas01mj@640: * @param node jquery or html element. mas01mj@640: * @return the ontology type of the object. mas01mj@640: */ mas01mj@640: jOWL.type = function(node){ mas01mj@640: var xmlNode = node.jquery ? node.get(0) : node; mas01mj@640: switch(xmlNode.nodeName){ mas01mj@640: case __.owl("Class") : return jOWL.Ontology.Class; mas01mj@640: case __.rdfs("Class") : return jOWL.Ontology.Class; //test mas01mj@640: case __.owl("Ontology") : return jOWL.Ontology; mas01mj@640: case __.owl("ObjectProperty") : return jOWL.Ontology.ObjectProperty; mas01mj@640: case __.owl("DatatypeProperty") : return jOWL.Ontology.DatatypeProperty; mas01mj@640: case __.owl("FunctionalProperty") : return jOWL.Ontology.Property; mas01mj@640: case __.rdf("Property") : return jOWL.Ontology.Property; mas01mj@640: case __.owl("InverseFunctionalProperty") : return jOWL.Ontology.ObjectProperty; mas01mj@640: case __.owl("TransitiveProperty") : return jOWL.Ontology.ObjectProperty; mas01mj@640: case __.owl("SymmetricProperty") : return jOWL.Ontology.ObjectProperty; mas01mj@640: //jOWL currently treats annotationproperties as string datatypeproperties. mas01mj@640: case __.owl("AnnotationProperty") : return jOWL.Ontology.DatatypeProperty; mas01mj@640: default : mas01mj@640: switch(xmlNode.namespaceURI){ mas01mj@640: case __.owl(): if(xmlNode.nodeName == __.owl("Thing") ){ return jOWL.Ontology.Individual;} return false; mas01mj@640: case __.rdf(): return false; mas01mj@640: case __.rdfs(): return false; mas01mj@640: default : return jOWL.Ontology.Individual; mas01mj@640: } mas01mj@640: } mas01mj@640: }; mas01mj@640: mas01mj@640: /** mas01mj@640: @param rdfID or Array mas01mj@640: @return Array of DOM (xml) Nodes mas01mj@640: */ mas01mj@640: jOWL.getXML = function(rdfID){ mas01mj@640: var node = []; mas01mj@640: function fetchFromIndex(rdfID){ mas01mj@640: var el = jOWL.index("ID")[rdfID]; mas01mj@640: return el ? el : null; mas01mj@640: } mas01mj@640: mas01mj@640: if(typeof rdfID == 'string'){ var q = fetchFromIndex(rdfID); if(q){ node.push(q);} } mas01mj@640: else if(jOWL.priv.Array.isArray(rdfID)){ //assume an array of string rdfIDs mas01mj@640: $.each(rdfID, function(){ mas01mj@640: var el = fetchFromIndex(this); if(el){ node.push(el);} mas01mj@640: }); mas01mj@640: } mas01mj@640: return node; mas01mj@640: }; mas01mj@640: mas01mj@640: /** Create new ontology elements */ mas01mj@640: jOWL.create = function(namespace, name, document){ mas01mj@640: var doc = document ? document : jOWL.document; mas01mj@640: mas01mj@640: var el = { mas01mj@640: attr : function(namespace, name, value){ mas01mj@640: if($.browser.msie){ mas01mj@640: var attribute = doc.createNode(2, namespace(name), namespace()); mas01mj@640: attribute.nodeValue = value; mas01mj@640: this.node.setAttributeNode(attribute); mas01mj@640: } mas01mj@640: else { this.node.setAttributeNS(namespace(), namespace(name), value);} mas01mj@640: return this; mas01mj@640: }, mas01mj@640: appendTo : function(node){ mas01mj@640: var n = node.node ? node.node : node; mas01mj@640: n.appendChild(this.node); mas01mj@640: return this; mas01mj@640: }, mas01mj@640: text : function(text, cdata){ mas01mj@640: var txt = cdata ? doc.createCDATASection(text) : doc.createTextNode(text); mas01mj@640: this.node.appendChild(txt); mas01mj@640: return this; mas01mj@640: } mas01mj@640: }; mas01mj@640: mas01mj@640: if($.browser.msie){ el.node = doc.createNode(1, namespace(name), namespace());} mas01mj@640: else { el.node = doc.createElementNS(namespace(), namespace(name));} mas01mj@640: return el; mas01mj@640: }; mas01mj@640: mas01mj@640: /** Create a blank ontology document */ mas01mj@640: jOWL.create.document = function(href){ mas01mj@640: var owl = []; mas01mj@640: var base = href || window.location.href+"#"; mas01mj@640: owl.push(''); mas01mj@640: owl.push('<'+__.rdf('RDF')+' xml:base="'+base+'" xmlns="'+base+'" '+__()+'>'); mas01mj@640: owl.push(' <'+__.owl('Ontology')+' '+__.rdf('about')+'=""/>'); mas01mj@640: owl.push(''); mas01mj@640: return jOWL.fromString(owl.join('\n')); mas01mj@640: }; mas01mj@640: mas01mj@640: /** Extracts RDFa syntax from current page and feeds it to jOWL, simple implementation, only classes for the time being */ mas01mj@640: jOWL.parseRDFa = function(fn, options){ mas01mj@640: var entries = options.node ? $("[typeof]", options.node) : $("[typeof]"); mas01mj@640: var doc = jOWL.create.document(); mas01mj@640: mas01mj@640: function property(p, node){ mas01mj@640: var arr = []; mas01mj@640: $("[property="+p+"]", node).each(function(){ arr.push($(this).attr('content') || $(this).html());}); mas01mj@640: if(node.attr('property') === p){ arr.push(node.attr('content') || node.html());} mas01mj@640: return arr; mas01mj@640: } mas01mj@640: mas01mj@640: function rel(p, node){ mas01mj@640: var arr = []; mas01mj@640: $("[rel="+p+"]", node).each(function(){ arr.push($(this).attr('resource'));}); mas01mj@640: if(node.attr("rel") === p){ arr.push(node.attr('resource'));} mas01mj@640: return arr; mas01mj@640: } mas01mj@640: mas01mj@640: function makeClass(node, ID){ mas01mj@640: var cl = jOWL.create(__.owl, "Class", doc).attr(__.rdf, 'about', ID).appendTo(doc.documentElement); mas01mj@640: mas01mj@640: var parents = property(__.rdfs("subClassOf"), node).concat(rel(__.rdfs("subClassOf"), node)); mas01mj@640: for(var i = 0;i mas01mj@640: Used for term searches, intend to (partially) replace it by a sparql-dl query later on mas01mj@640: options: mas01mj@640: filter: filter on a specific type, possible values: Class, Thing, ObjectProperty, DatatypeProperty mas01mj@640: exclude: exclude specific types, not fully implemented mas01mj@640: */ mas01mj@640: jOWL.query = function(match, options){ mas01mj@640: options = $.extend({exclude : false}, options); mas01mj@640: if(options.filter == 'Class'){ options.filter = __.owl("Class");} mas01mj@640: var that = this; mas01mj@640: //filter : [], exclude : false mas01mj@640: var items = new jOWL.Ontology.Array(); mas01mj@640: var jsonobj = {}; mas01mj@640: var test = jOWL.index("dictionary"); mas01mj@640: mas01mj@640: function store(item){ mas01mj@640: var include = false, i = 0; mas01mj@640: if(options.filter){ mas01mj@640: if(typeof options.filter == 'string'){ include = (options.filter == item[3]);} mas01mj@640: else { for(i = 0;i -1){ mas01mj@640: if(options.locale){ if(options.locale == item[2]){ store(item);} } mas01mj@640: else { store(item);} mas01mj@640: } mas01mj@640: } mas01mj@640: return jsonobj; mas01mj@640: }; mas01mj@640: mas01mj@640: /** mas01mj@640: allows asynchronous looping over arrays (prevent bowser freezing). mas01mj@640: arr the array to loop asynchonrously over. mas01mj@640: options.modify(item) things to do with each item of the array mas01mj@640: options.onUpdate array the size of chewsize or smaller, containing processed entries mas01mj@640: options.onComplete(array of results) function triggered when looping has completed mas01mj@640: */ mas01mj@640: jOWL.throttle =function(array, options){ mas01mj@640: options = $.extend({ mas01mj@640: modify : function(result){}, mas01mj@640: //onUpdate : function(arr){}, mas01mj@640: onComplete : function(arr){}, mas01mj@640: async : true, mas01mj@640: chewsize : 5, mas01mj@640: startIndex : 0, mas01mj@640: timing : 5 mas01mj@640: }, options); mas01mj@640: var temp = array.jOWL ? array.items : (array.jquery) ? $.makeArray(array) : array; mas01mj@640: var items = options.startIndex ? temp.slice(startIndex) : temp.concat(); //clone the array mas01mj@640: var results = []; mas01mj@640: mas01mj@640: (function(){ mas01mj@640: var count = options.chewsize; mas01mj@640: var a = []; mas01mj@640: while (count > 0 && items.length > 0) mas01mj@640: { mas01mj@640: var item = items.shift(); count--; mas01mj@640: var result = options.modify.call(item, item); mas01mj@640: if(result){ results.push(result); a.push(result);} mas01mj@640: } mas01mj@640: if(options.onUpdate){ options.onUpdate(a);} mas01mj@640: mas01mj@640: if(items.length> 0){ mas01mj@640: if(options.async){ setTimeout(arguments.callee, options.timing);} mas01mj@640: else {arguments.callee();} mas01mj@640: } mas01mj@640: else{ options.onComplete(results);} mas01mj@640: })(); mas01mj@640: }; mas01mj@640: mas01mj@640: /** Creates a new resultobj for the SPARQL-DL functionality */ mas01mj@640: jOWL.SPARQL_DL_Result = function(){ mas01mj@640: this.assert = undefined; mas01mj@640: this.head = {}; //associative array of query parameters, with value jOWL Array of results mas01mj@640: this.results = []; //sparql-dl bindings mas01mj@640: this.isBound = false; mas01mj@640: }; mas01mj@640: mas01mj@640: jOWL.SPARQL_DL_Result.prototype = { mas01mj@640: sort : function(param){ mas01mj@640: if(!param){ throw "parameter must be defined for sort function";} mas01mj@640: function sortResults(a, b){ mas01mj@640: var o = a[param].name || a[param]; mas01mj@640: var p = b[param].name || b[param]; mas01mj@640: return (o < p) ? -1 : 1; mas01mj@640: } mas01mj@640: if(this.results){ this.results.sort(sortResults); } mas01mj@640: }, mas01mj@640: jOWLArray : function(param){ mas01mj@640: if(!param){ throw "parameter must be defined for jOWLArray function";} mas01mj@640: var arr = new jOWL.Ontology.Array(); mas01mj@640: for(var i=0;i=0;i--){ mas01mj@640: var valueX = this.results[i][x]; mas01mj@640: if(valueX){ mas01mj@640: if(!results.mappings[x].contains(valueX)){ mas01mj@640: this.results.splice(i, 1); mas01mj@640: continue; mas01mj@640: } mas01mj@640: if(multimapping){ mas01mj@640: var keyArr= otherKeys[valueX.URI]; mas01mj@640: //ignoring the opposite for now (assuming original key x is unique (limits statements)) mas01mj@640: //TODO: improve these result merging methods/flexibility mas01mj@640: for(var oK = 0; oK < keyArr.length;oK++){ mas01mj@640: var obj = (oK === 0) ? this.results[i] : {}; mas01mj@640: var valueY = keyArr[oK]; mas01mj@640: obj[x] = valueX; mas01mj@640: for(yK in valueY){ obj[yK] = valueY[yK]; } mas01mj@640: toAdd.push(obj); mas01mj@640: } mas01mj@640: this.results.splice(i, 1); mas01mj@640: } mas01mj@640: } mas01mj@640: } mas01mj@640: } mas01mj@640: this.results = this.results.concat(toAdd); mas01mj@640: } mas01mj@640: }; mas01mj@640: /** Creates a new query for the SPARQL-DL functionality */ mas01mj@640: jOWL.SPARQL_DL_Query = function(syntax, parameters){ mas01mj@640: this.parse(syntax); mas01mj@640: this.fill(parameters); mas01mj@640: this.entries = this.entries.sort(this.sort); mas01mj@640: }; mas01mj@640: mas01mj@640: jOWL.SPARQL_DL_Query.prototype = { mas01mj@640: parse : function(syntax){ mas01mj@640: var r2 = /(\w+)[(]([^)]+)[)]/; mas01mj@640: var entries = syntax.match(/(\w+[(][^)]+[)])/g); mas01mj@640: if(!entries){ this.error = "invalid abstract sparql-dl syntax"; return;} mas01mj@640: entries = jOWL.priv.Array.unique(entries); mas01mj@640: for(var i = 0;i=0;i--){ mas01mj@640: if(this.arr[i][keyX]){ mas01mj@640: if(!arr[this.arr[i][keyX].URI]){ arr[this.arr[i][keyX].URI] = []; } mas01mj@640: arr[this.arr[i][keyX].URI].push(this.arr[i]); mas01mj@640: } mas01mj@640: } mas01mj@640: return arr; mas01mj@640: }, mas01mj@640: get : function(key) mas01mj@640: { mas01mj@640: return (this.mappings[key]) ? this.mappings[key] : new jOWL.Ontology.Array(); mas01mj@640: }, mas01mj@640: getArray : function(){ mas01mj@640: //check mappings for presence, discard arr entries based on that, return remainder. mas01mj@640: for(var i = this.arr.length - 1;i>=0;i--){ mas01mj@640: var binding = this.arr[i], splice = false; mas01mj@640: for(key in binding){ mas01mj@640: if(!splice){ mas01mj@640: splice = (!this.mappings[key] || !this.mappings[key].contains(binding[key])); mas01mj@640: } mas01mj@640: } mas01mj@640: if(splice){ mas01mj@640: this.arr.splice(i, 1); mas01mj@640: } mas01mj@640: } mas01mj@640: return this; mas01mj@640: } mas01mj@640: }; mas01mj@640: mas01mj@640: /** mas01mj@640: Support for abstract SPARQl-DL syntax mas01mj@640: options.onComplete: function triggered when all individuals have been looped over mas01mj@640: options.childDepth: depth to fetch children, default 5, impacts performance mas01mj@640: options.chewsize: arrays will be processed in smaller chunks (asynchronous), with size indicated by chewsize, default 10 mas01mj@640: options.async: default true, query asynchronously mas01mj@640: parameters: prefill some sparql-dl parameters with jOWL objects mas01mj@640: execute: start query, results are passed through options.onComplete mas01mj@640: */ mas01mj@640: jOWL.SPARQL_DL = function(syntax, parameters, options){ mas01mj@640: if(!(this instanceof arguments.callee)){ return new jOWL.SPARQL_DL(syntax, parameters, options);} mas01mj@640: var self = this; mas01mj@640: this.parameters = $.extend({}, parameters); mas01mj@640: this.query = new jOWL.SPARQL_DL_Query(syntax, this.parameters).entries; mas01mj@640: this.result = new jOWL.SPARQL_DL_Result(); mas01mj@640: this.options = $.extend({onComplete: function(results){}}, options); mas01mj@640: }; mas01mj@640: mas01mj@640: jOWL.SPARQL_DL.prototype = { mas01mj@640: error: function(msg){ this.result.error = msg; return this.options.onComplete(this.result);}, mas01mj@640: /** mas01mj@640: if(options.async == false) then this method returns the result of options.onComplete, mas01mj@640: no matter what, result is always passed in options.onComplete mas01mj@640: */ mas01mj@640: execute : function(options){ mas01mj@640: var self = this; mas01mj@640: this.options = $.extend(this.options, options); mas01mj@640: if(this.query.error){ return this.error(this.query.error);} mas01mj@640: mas01mj@640: var resultobj = this.result; mas01mj@640: var i = 0; mas01mj@640: var loopoptions = $.extend({}, this.options); mas01mj@640: loopoptions.onComplete = function(results){ i++; resultobj = results; loop(i);}; mas01mj@640: mas01mj@640: if(!this.query.length){ mas01mj@640: resultobj.error = "no query found or query did not parse properly"; mas01mj@640: return self.options.onComplete(resultobj); mas01mj@640: } mas01mj@640: mas01mj@640: function loop(i){ mas01mj@640: if(i < self.query.length){ mas01mj@640: self.process(self.query[i], resultobj, loopoptions ); mas01mj@640: } mas01mj@640: else { mas01mj@640: for(var j =0;j 0){ match = true;} mas01mj@640: return; mas01mj@640: } mas01mj@640: if(!restrictions.length){ return;} mas01mj@640: restrictions.each(function(){ mas01mj@640: var binding = new _Binding(results); mas01mj@640: if(options.filterSource){ mas01mj@640: binding.bind(options.filterSource, source); mas01mj@640: if(!options.filterProperty && !options.filterTarget){ results.add(binding); return false;} mas01mj@640: } mas01mj@640: if(options.filterProperty){ mas01mj@640: binding.bind(options.filterProperty, this.property); mas01mj@640: } mas01mj@640: if(options.filterTarget){ mas01mj@640: binding.bind(options.filterTarget, this.getTarget()); mas01mj@640: } mas01mj@640: results.add(binding); mas01mj@640: }); mas01mj@640: return true; mas01mj@640: }); mas01mj@640: if(options.assert){ mas01mj@640: resultobj.assert = match; mas01mj@640: return resultobj.assert; mas01mj@640: } mas01mj@640: if(options.filterSource){ resultobj.filter(options.filterSource, results.get(options.filterSource));} mas01mj@640: if(options.filterProperty){ resultobj.filter(options.filterProperty, results.get(options.filterProperty));} mas01mj@640: if(options.filterTarget) { resultobj.filter(options.filterTarget, results.get(options.filterTarget));} mas01mj@640: resultobj.bind(results.getArray()); mas01mj@640: }, mas01mj@640: hasClassID: function(match, classID){ mas01mj@640: if(Object.prototype.toString.call(classID) === '[object Array]'){ mas01mj@640: for(var i =0;i