Mercurial > hg > audiodb
comparison examples/browser/web/js/jOWL.js @ 640:901803e1305f
First instance of audioDB browser code.
author | mas01mj |
---|---|
date | Thu, 08 Oct 2009 11:19:11 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
639:2eaea1afd6b3 | 640:901803e1305f |
---|---|
1 /** | |
2 * jOWL - a jQuery plugin for traversing and visualizing OWL-DL documents. | |
3 * Creator - David Decraene | |
4 * Version 1.0 | |
5 * Website: | |
6 * http://Ontologyonline.org | |
7 * Licensed under the MIT license | |
8 * http://www.opensource.org/licenses/mit-license.php | |
9 * Verified with JSLint | |
10 * http://www.jslint.com/ | |
11 */ | |
12 | |
13 jOWL = window.jOWL = function( resource, options ){ return jOWL.getResource( resource, options ); }; | |
14 jOWL.version = "1.0"; | |
15 | |
16 /** for debugging compatibility */ | |
17 try { console.log('...'); } catch(e) { console = window.console = { log: function() {} } } | |
18 if ($.browser.opera && opera.postError) { console = window.console = { log : function(){opera.postError(arguments); } }; } | |
19 | |
20 | |
21 | |
22 (function($){ | |
23 | |
24 /** | |
25 * if no param: @return string of main namespaces | |
26 * if 1 param: assume a documentElement, parse namespaces | |
27 * if prefix & URI: Bind prefix to namespace URI | |
28 */ | |
29 jOWL.NS = function(prefix, URI){ | |
30 if(!arguments.length) | |
31 { 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()+"'";} | |
32 | |
33 if(arguments.length == 1){ | |
34 var attr = prefix.get(0).attributes; | |
35 for(var i=0;i<attr.length;i++){ | |
36 var nn = attr[i].nodeName.split(':'); | |
37 if(nn.length == 2){ | |
38 if(attr[i].nodeValue == jOWL.NS.owl.URI){ jOWL.NS.owl.prefix = nn[1];} | |
39 else if(attr[i].nodeValue == jOWL.NS.rdf.URI){ jOWL.NS.rdf.prefix = nn[1];} | |
40 else if(attr[i].nodeValue == jOWL.NS.rdfs.URI){ jOWL.NS.rdfs.prefix = nn[1];} | |
41 else if(attr[i].nodeValue == jOWL.NS.xsd.URI){ jOWL.NS.xsd.prefix = nn[1];} | |
42 else { jOWL.NS(nn[1], attr[i].nodeValue);} | |
43 } | |
44 } | |
45 jOWL.namespace = prefix.xmlAttr('xml:base') || prefix.xmlAttr('xmlns'); | |
46 return; | |
47 } | |
48 jOWL.NS[prefix] = function(element){ | |
49 if(element){ | |
50 return (arguments.callee.prefix == 'base') ? element : arguments.callee.prefix + ":" + element; | |
51 } | |
52 return arguments.callee.URI; | |
53 }; | |
54 jOWL.NS[prefix].prefix = prefix; | |
55 jOWL.NS[prefix].URI = URI; | |
56 }; | |
57 | |
58 var __ = jOWL.NS; | |
59 | |
60 /** set Main namespaces */ | |
61 __("owl", "http://www.w3.org/2002/07/owl#"); | |
62 __("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); | |
63 __("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); | |
64 __("xsd", "http://www.w3.org/2001/XMLSchema#"); | |
65 | |
66 /** jQuery function additions for easy parsing of identities */ | |
67 $.fn.extend({ | |
68 /** Used for Opera compatibility when parsing xml attributes, nodeName must be checked, in contrast to native jquery call attr() */ | |
69 xmlAttr : function(nodeName){ | |
70 var t = this[0].attributes; if(!t){ return;} | |
71 for(var i =0;i<t.length;i++){ | |
72 if(t[i].nodeName == nodeName){ return t[i].nodeValue;} | |
73 } | |
74 }, | |
75 RDF_ID : function(match){ | |
76 var res = this.xmlAttr(__.rdf('ID')); | |
77 if(!res){ return false;} | |
78 res = jOWL.resolveURI(res); | |
79 if(match){ | |
80 return res.toLowerCase() == (jOWL.resolveURI(match.toString())).toLowerCase();} | |
81 return res; | |
82 }, | |
83 RDF_Resource : function(match){ | |
84 function getClassName(dom){ | |
85 var cl = jOWL.Xpath(__.owl("Class"), dom); | |
86 if(cl.length == 1){ return new jOWL.Ontology.Class(cl).URI;} | |
87 return false; | |
88 } | |
89 if(!this.length){ return false;} | |
90 var rsrc = this.xmlAttr(__.rdf('resource')); | |
91 if(!rsrc){ | |
92 var dom = this.get(0); | |
93 switch(dom.nodeName){ | |
94 case __.rdfs("subClassOf"): rsrc = getClassName(dom); break; | |
95 case __.owl("disjointWith"): rsrc = getClassName(dom); break; | |
96 case __.owl("allValuesFrom"): rsrc = getClassName(dom); break; | |
97 case __.owl("someValuesFrom"): rsrc = getClassName(dom); break; | |
98 case __.owl("onProperty"): | |
99 var t = jOWL.Xpath(__.owl("ObjectProperty"), dom); | |
100 if(t.length === 0){ t = jOWL.Xpath(__.owl("DatatypeProperty"), dom);} | |
101 if(t.length === 0){ t = jOWL.Xpath(__.owl("FunctionalProperty"), dom);} | |
102 rsrc = t.xmlAttr(__.rdf('about')); break; | |
103 default: return false; | |
104 } | |
105 } | |
106 if(!rsrc){ return false;} | |
107 rsrc = jOWL.resolveURI(rsrc); | |
108 if(match){ return rsrc.toLowerCase() == (jOWL.resolveURI(match.toString())).toLowerCase();} | |
109 return rsrc; | |
110 }, | |
111 RDF_About : function(match){ | |
112 var res = this.xmlAttr(__.rdf('about')); | |
113 if(!res){ return false;} | |
114 res = jOWL.resolveURI(res); | |
115 if(match){ | |
116 return res.toLowerCase() == (jOWL.resolveURI(match.toString())).toLowerCase();} | |
117 return res; | |
118 } | |
119 }); | |
120 | |
121 /** Check XPath implementation */ | |
122 if( document.implementation.hasFeature("XPath", "3.0") ){ | |
123 XMLDocument.prototype.selectNodes = function(cXPathString, xNode){ | |
124 if( !xNode ){ xNode = this;} | |
125 var oNSResolver = this.createNSResolver(this.documentElement); | |
126 var aItems = this.evaluate(cXPathString, xNode, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); var aResult = []; for( var i = 0; i < aItems.snapshotLength; i++){ aResult[i] = aItems.snapshotItem(i);} | |
127 return aResult; | |
128 }; | |
129 Element.prototype.selectNodes = function(cXPathString){ | |
130 if(this.ownerDocument.selectNodes) { return this.ownerDocument.selectNodes(cXPathString, this);} | |
131 else{throw "For XML Elements Only";} | |
132 }; | |
133 XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode){ if( !xNode ){ xNode = this;} | |
134 var xItems = this.selectNodes(cXPathString, xNode); if( xItems.length > 0 ){ return xItems[0];} else { return null;} | |
135 }; | |
136 Element.prototype.selectSingleNode = function(cXPathString){ | |
137 if(this.ownerDocument.selectSingleNode) { return this.ownerDocument.selectSingleNode(cXPathString, this);} | |
138 else{throw "For XML Elements Only";} | |
139 }; | |
140 } | |
141 | |
142 /** @return A jQuery array of xml elements */ | |
143 jOWL.Xpath = function(selector, elem){ | |
144 var node = null; | |
145 if(elem){ if(elem.each){ node = elem.get(0);} else { node = elem;} } | |
146 var arr = node ? node.selectNodes(selector) : jOWL.document.selectNodes(selector); | |
147 if($.browser.msie){ return $($.makeArray(arr));} return $(arr); //this is needed for IE, it returns a length of 1 on empty node array | |
148 }; | |
149 | |
150 /** @return a String array of class references */ | |
151 jOWL.Xpath.classes = function(jnode){ | |
152 var cl = []; | |
153 jOWL.Xpath(__.rdfs("subClassOf"), jnode) | |
154 .each(function(){ | |
155 var res = $(this).RDF_Resource(); | |
156 if(res){ cl.push(res);} | |
157 }); | |
158 | |
159 jOWL.Xpath(__.owl("intersectionOf")+"/"+__.owl("Class"), jnode) | |
160 .each(function(){ | |
161 var p = $(this).RDF_About(); if(p){ cl.push(p);} | |
162 }); | |
163 return cl; | |
164 }; | |
165 | |
166 /** Functions stored in jOWL.priv are intended for local access only, to avoid a closure function */ | |
167 jOWL.priv = { | |
168 /** Arrray functions */ | |
169 Array : { | |
170 isArray : function(array){ | |
171 return Object.prototype.toString.call(array) === '[object Array]'; | |
172 }, | |
173 pushUnique : function(array, item){ | |
174 if(jOWL.priv.Array.getIndex(array, item) === -1){ array.push(item); return true;} | |
175 return false; | |
176 }, | |
177 getIndex : function(array, item){ | |
178 for (var i=0; i<array.length; i++){ if(item == array[i]){ return i;} } | |
179 return -1; | |
180 }, | |
181 /** Sorted array as input, returns the same array without duplicates. */ | |
182 unique : function(array){ | |
183 var result = []; var lastValue=""; | |
184 for (var i=0; i<array.length; i++) | |
185 { | |
186 var curValue=array[i]; | |
187 if(curValue != lastValue){ result[result.length] = curValue;} | |
188 lastValue=curValue; | |
189 } | |
190 return result; | |
191 } | |
192 } | |
193 }; | |
194 | |
195 /** Make values work with jOWL.Ontology.Array */ | |
196 jOWL.Literal = function(value){ | |
197 this.name = value; | |
198 }; | |
199 | |
200 /** Access to the owl:Ontology element, also the main coding namespace for ontology objects */ | |
201 jOWL.Ontology = function(){ | |
202 if(!(this instanceof arguments.callee)){ return new jOWL.Ontology();} | |
203 this.parse(jOWL.Xpath("/"+__.rdf("RDF")+"/"+__.owl("Ontology"))); | |
204 return this; | |
205 }; | |
206 | |
207 /** 'superclass' for referencable ontology objects */ | |
208 jOWL.Ontology.Thing = function(jnode){ | |
209 this.parse(jnode); | |
210 }; | |
211 | |
212 jOWL.Ontology.Thing.prototype = { | |
213 jOWL : jOWL.version, | |
214 equals : function(id){ | |
215 var URI = (typeof id == "string") ? jOWL.resolveURI(id) : id.URI; | |
216 return URI === this.URI; | |
217 }, | |
218 /** Initialization */ | |
219 parse : function(jnode){ | |
220 if(!jnode.length){ return;} | |
221 var identifier; | |
222 if(typeof jnode == 'string'){ | |
223 identifier = jnode; | |
224 jnode = $(); | |
225 } | |
226 else { | |
227 identifier = jnode.RDF_ID() || jnode.RDF_About(); | |
228 if(!identifier){identifier = "anonymousOntologyObject"; | |
229 this.isAnonymous = true; | |
230 } | |
231 } | |
232 identifier = jOWL.resolveURI(identifier); | |
233 this.isExternal = jOWL.isExternal(identifier); | |
234 if(this.isExternal){this.baseURI = this.isExternal[0]; this.name = this.isExternal[1]; this.URI = this.baseURI+this.name;} | |
235 else { this.baseURI = jOWL.namespace; this.name = identifier; this.URI = this.name;} | |
236 this.jnode = jnode; | |
237 this.type = jnode.get(0).nodeName; | |
238 }, | |
239 /** @return A jQuery array of elements matching the annotation (qualified name or annotation Property) */ | |
240 annotations : function(annotation){ | |
241 return jOWL.Xpath(annotation, this.jnode); | |
242 }, | |
243 /** @return rdfs:comment annotations */ | |
244 description : function(){ | |
245 return $.map(this.annotations(__.rdfs('comment')), function(n){ return $(n).text();}); | |
246 }, | |
247 /** | |
248 @return Array of Arrays, where secondary array is of form: [0] = term (rdfs:label) , [1] = identifier, [2] = language; [3] = type of object | |
249 example: | |
250 [ | |
251 ["bleu", "blue", "fr", "owl:Class"] | |
252 ] | |
253 */ | |
254 terms : function(){ | |
255 var terms = [], self = this; | |
256 if(jOWL.options.dictionary.addID && this.name != "anonymousOntologyObject"){ terms.push([this.name.beautify(), this.URI, jOWL.options.defaultlocale, this.type]);} | |
257 this.annotations(__.rdfs('label')).each(function(){ | |
258 var lbl = $(this); | |
259 var locale = lbl.xmlAttr("xml:lang") || jOWL.options.defaultlocale; | |
260 var txt = lbl.text(); | |
261 var match = false; | |
262 for(var i =0;i<terms.length;i++){ | |
263 if(terms[i][0].toUpperCase() == txt.toUpperCase() && terms[i][2] == locale){ match = true;} | |
264 } | |
265 if(!match){ terms.push([lbl.text(), self.URI, locale, self.type]);} | |
266 }); | |
267 return terms; | |
268 }, | |
269 /** @return A representation name */ | |
270 label : function(){ | |
271 var label = false; | |
272 this.annotations(__.rdfs('label')).each(function(){ | |
273 var $label = $(this); | |
274 if(jOWL.options.locale){ | |
275 var lang = $label.xmlAttr('xml:lang') || jOWL.options.defaultlocale; | |
276 if(lang == jOWL.options.locale){ label = $label.text(); return false;} | |
277 } else { label = $label.text(); return false;} | |
278 }); | |
279 if(label){ return label;} | |
280 if(this.name == "anonymousOntologyObject"){ return jOWL.Manchester(this) || "anonymous Object";} | |
281 if(jOWL.options.niceClassLabels && (this.isClass || this.isThing)){ | |
282 return this.name.beautify(); | |
283 } | |
284 return this.name; | |
285 }, | |
286 /** Binds the Ontology element to the jQuery element for visual representation | |
287 * @return jQuery Element | |
288 */ | |
289 bind : function(jqelem){ | |
290 return jqelem.text(this.label()).attr('typeof', this.type).attr('title', this.URI); | |
291 } | |
292 }; | |
293 | |
294 jOWL.Ontology.prototype = jOWL.Ontology.Thing.prototype; | |
295 | |
296 /** used for jOWL.Ontology.Individual.sourceof */ | |
297 jOWL.priv.testObjectTarget = function(target, matchtarget){ | |
298 if(target.isArray){ | |
299 for(var i=0;i<target.length;i++){ | |
300 if(jOWL.priv.testObjectTarget(target.get(i), matchtarget)){ return true;} | |
301 } | |
302 return false; | |
303 } | |
304 //if the target is a class, fetch individuals instead. | |
305 else if(target.isClass){ | |
306 var a = target.individuals(); | |
307 for(var i=0;i<a.length;i++){ | |
308 if(a.get(i).URI == matchtarget){ return true;} | |
309 } | |
310 } | |
311 else if(target.URI == matchtarget){ return true;} | |
312 return false; | |
313 }; | |
314 | |
315 /** access to Individuals of the ontology*/ | |
316 jOWL.Ontology.Individual = function(jnode, owlclass){ | |
317 this.parse(jnode); | |
318 if(this.type == __.owl("Thing")){ | |
319 var t = jOWL.Xpath(__.rdf('type'), this.jnode); | |
320 if(!t.length){ throw "unable to find a Class for the Individual "+this.name;} | |
321 this.Class = $(t[0]).RDF_Resource(); | |
322 } | |
323 else { | |
324 this.Class = jOWL.resolveURI(jnode.get(0)); | |
325 } | |
326 this.type = __.owl("Thing"); | |
327 if(owlclass){ this.owlClass(owlclass);} | |
328 }; | |
329 | |
330 jOWL.Ontology.Individual.prototype = $.extend({}, jOWL.Ontology.Thing.prototype, { | |
331 isThing : true, | |
332 /** @return The owl:Class */ | |
333 owlClass : function(owlclass){ | |
334 if(owlclass){ jOWL.data(this.name, "class", owlclass);} | |
335 else { | |
336 var cl = jOWL.data(this.name, "class"); | |
337 if(!cl){ cl = jOWL(this.Class); if(cl){ this.owlClass(cl);} } | |
338 return cl; | |
339 } | |
340 }, | |
341 /** Access to restrictions */ | |
342 sourceof : function(property, target, options){ | |
343 options = $.extend({ | |
344 inherited : true, // add restrictions specified on parents as well | |
345 transitive : true, | |
346 ignoreGenerics : false, //if a parent has an identical property, with another target 'Thing', skip that restriction | |
347 ignoreClasses : true, | |
348 valuesOnly : true | |
349 }, options); | |
350 | |
351 var results = new jOWL.Ontology.Array(); | |
352 | |
353 this.jnode.children().filter(function(){return (this.prefix != __.rdfs.prefix && this.prefix != __.rdf.prefix && this.prefix != __.owl.prefix);}) | |
354 .each(function(){ | |
355 var restriction = new jOWL.Ontology.Restriction($(this)); | |
356 var propertyMatch = property ? false : true; | |
357 var targetMatch = target ? false : true; | |
358 | |
359 if(!propertyMatch){ | |
360 if( property.isArray){ propertyMatch = property.contains(restriction.property);} | |
361 else { propertyMatch = (property.URI == restriction.property.URI);} | |
362 if(!propertyMatch){ return;} | |
363 } | |
364 | |
365 if(!target){ | |
366 if(options.transitive && restriction.property.isTransitive && !options.ignoreGenerics){ | |
367 var rTarget = restriction.getTarget(); | |
368 var transitives = rTarget.sourceof(restriction.property, null, options); | |
369 results.concat(transitives); | |
370 } | |
371 } | |
372 else { | |
373 if(restriction.property.isObjectProperty){ | |
374 targetMatch = jOWL.priv.testObjectTarget(target, restriction.target); | |
375 if(!targetMatch && options.transitive && restriction.property.isTransitive){ | |
376 var rTransitives = restriction.getTarget().sourceof(restriction.property, target, options); | |
377 if(rTransitives.length > 0){ targetMatch = true;} | |
378 } | |
379 } | |
380 else if(restriction.property.isDatatypeProperty){ | |
381 targetMatch = restriction.property.assert(restriction.target, target); | |
382 } | |
383 else { targetMatch = (target == restriction.target);} | |
384 } | |
385 if(propertyMatch && targetMatch){ results.pushUnique(restriction);} | |
386 | |
387 }); | |
388 if(options.inherited){ | |
389 var clRestrictions = this.owlClass().sourceof(property, target, options) | |
390 .each(function(){ | |
391 //target can be a class, null, a duplicate individual... | |
392 var clRestr = this; | |
393 if(options.valuesOnly && clRestr.target === null){return;} | |
394 var clTarget = this.getTarget(); | |
395 if(clTarget.isClass && options.ignoreClasses){ return;} | |
396 | |
397 var containsProperty = false; | |
398 for(var i = 0;i<results.length;i++){ | |
399 var restr = results.get(i); | |
400 if(restr.property.URI == clRestr.property.URI){ | |
401 containsProperty = true; | |
402 if(!options.ignoreGenerics){ | |
403 if(clRestr.target != restr.target){ results.pushUnique(clRestr);} | |
404 } | |
405 } | |
406 } | |
407 if(!containsProperty){ results.pushUnique(clRestr);} | |
408 }); | |
409 } | |
410 return results; | |
411 | |
412 }, | |
413 localRestrictions : function(property, target){ | |
414 return this.sourceof(property, target, {inherited : false, transitive : false }); | |
415 }, | |
416 /** Include generic will add transitivity reasoning */ | |
417 valueRestrictions : function(includeGeneric){ | |
418 return this.sourceof(null, null, {ignoreGenerics : !includeGeneric, valuesOnly : true }); | |
419 } | |
420 }); | |
421 | |
422 /** jNode is of type owl:Restriction */ | |
423 jOWL.Ontology.Restriction = function(jnode){ | |
424 | |
425 var jprop, prop, op, restrtype; | |
426 | |
427 this.cachedTarget = null; | |
428 | |
429 if(jnode.get(0).nodeName != __.owl("Restriction")){ | |
430 this.property = jOWL(jOWL.resolveURI(jnode.get(0)), {type: "property"}); | |
431 this.target = jnode.RDF_Resource() || jnode.text(); | |
432 restrtype = "Individual"; | |
433 } | |
434 else | |
435 { | |
436 jprop = jOWL.Xpath(__.owl("onProperty"), jnode); | |
437 prop = jprop.RDF_Resource(); if(!prop){ throw "no property found for the given owl:restriction";} | |
438 op = jprop.siblings(); | |
439 restrtype = op.get(0).nodeName; | |
440 this.property = jOWL(prop, {type: "property"}); | |
441 this.target = null; //string only | |
442 } | |
443 | |
444 this.restriction = { minCard: false, maxCard : false, some: [], all : [], value : false }; | |
445 this.type = jnode.get(0).nodeName; | |
446 this.isAnonymous = true; | |
447 this.isValueRestriction = (restrtype == __.owl('someValuesFrom') || restrtype == __.owl('allValuesFrom') || restrtype == __.owl('hasValue')); | |
448 this.isCardinalityRestriction = (restrtype == __.owl('cardinality') || restrtype == __.owl('maxCardinality') || restrtype == __.owl('minCardinality')); | |
449 | |
450 if(!this.property || !restrtype){ throw "badly formed owl:restriction";} | |
451 switch(restrtype){ | |
452 case __.owl('cardinality'): this.restriction.minCard = this.restriction.maxCard = parseInt(op.text(), 10); break; | |
453 case __.owl('maxCardinality'): this.restriction.maxCard = parseInt(op.text(), 10); break; | |
454 case __.owl('minCardinality'): this.restriction.minCard = parseInt(op.text(), 10); break; | |
455 case __.owl('hasValue'): var res = op.RDF_Resource(); if(res){ this.target = res;} break; | |
456 } | |
457 if(this.property.isObjectProperty){ | |
458 if(this.isCardinalityRestriction && this.property.range){ this.target = this.property.range;} | |
459 else if(this.isValueRestriction){ | |
460 var t = op.RDF_Resource(); | |
461 if(t == "anonymousOntologyObject"){//nested groupings, anonymous classes | |
462 this.cachedTarget = new jOWL.Ontology.Class(jOWL.Xpath(__.owl("Class"), op)); | |
463 } | |
464 this.target = t; | |
465 } | |
466 } | |
467 | |
468 var suffix = this.target || this.restrtype; | |
469 this.name = this.property.name+'#'+suffix; | |
470 return this; | |
471 }; | |
472 | |
473 jOWL.Ontology.Restriction.prototype = { | |
474 jOWL : jOWL.version, | |
475 isRestriction : true, | |
476 bind : function(){return null;}, | |
477 merge : function(crit){ | |
478 if(this.isCardinalityRestriction && crit.isValueRestriction ){ this.target = crit.target; return true;} | |
479 else if(this.isValueRestriction && crit.isCardinalityRestriction){ | |
480 switch(crit.restrtype){ | |
481 case __.owl('cardinality'): this.restriction.minCard = this.restriction.maxCard = crit.restriction.minCard; return true; | |
482 case __.owl('minCardinality'): this.restriction.minCard = crit.restriction.minCard; return true; | |
483 case __.owl('maxCardinality'): this.restriction.maxCard = crit.restriction.maxCard; return true; | |
484 } | |
485 } | |
486 return false; | |
487 }, | |
488 getTarget : function(){ | |
489 if(!this.target){ return jOWL('Thing');} | |
490 if(this.cachedTarget){ return this.cachedTarget;} | |
491 this.cachedTarget = (this.property.isObjectProperty) ? jOWL(this.target) : new jOWL.Literal(this.target); | |
492 return this.cachedTarget; | |
493 }, | |
494 equals : function(restr){ | |
495 if(!restr.isRestriction){ return false;} | |
496 if(this.property.URI == restr.property.URI){ | |
497 if(this.target == 'anonymousOntologyObject'){return false;}//oneof lists etc unsupported right now | |
498 if(this.target && this.target === restr.target){ return true;} | |
499 } | |
500 return false; | |
501 } | |
502 }; | |
503 | |
504 /** Datatype Logic, local functions */ | |
505 jOWL.priv.Dt = function(options){ | |
506 this.settings = $.extend({base: null, pattern : null, assert: function(b){return true;}, match: function(a, b){return true;}}, options); | |
507 this.base = jOWL.Ontology.Datatype[this.settings.base]; | |
508 }; | |
509 | |
510 jOWL.priv.Dt.prototype = { | |
511 sanitize : function(b){ | |
512 if(this.settings.sanitize){ return this.settings.sanitize(b);} | |
513 if(this.base && this.base.sanitize){ return this.base.sanitize(b);} | |
514 }, | |
515 assert : function(b){ | |
516 var v = this.sanitize(b); if(v !== undefined){ b = v;} | |
517 if(this.base && !this.base.assert(b)){ return false;} | |
518 if(this.settings.pattern && !this.settings.pattern.test(b)){ return false;} | |
519 return this.settings.assert(b); | |
520 }, | |
521 match : function(a, b){ | |
522 var v = this.sanitize(b); if(v !== undefined){ b = v;} | |
523 if(!this.assert(b)){ return false;} | |
524 if(this.base && !this.base.match(a, b)){ return false;} | |
525 return this.settings.match(a, b); | |
526 } | |
527 }; | |
528 | |
529 jOWL.Ontology.Datatype = function(URI, options){ | |
530 jOWL.Ontology.Datatype[URI] = new jOWL.priv.Dt(options); | |
531 }; | |
532 | |
533 /** Datatype Definitions */ | |
534 jOWL.Ontology.Datatype(__.xsd()+"integer", {sanitize : function(x){return parseInt(x, 10);}, assert : function(x){ return Math.round(x) == x;}, match : function(a, b){ | |
535 var check = parseInt(a, 10); | |
536 if(!isNaN(check)){ return check == b;} | |
537 var arr = a.split('&&'); | |
538 for(var i=0;i<arr.length;i++){ arr[i] = b+arr[i];} | |
539 try { | |
540 return eval(arr.join(' && ')); | |
541 } catch(e){ return false;} | |
542 } }); | |
543 jOWL.Ontology.Datatype(__.xsd()+"positiveInteger", {base: __.xsd()+"integer", assert : function(x){ return x > 0;} }); | |
544 jOWL.Ontology.Datatype(__.xsd()+"decimal", {base: __.xsd()+"integer" }); | |
545 jOWL.Ontology.Datatype(__.xsd()+"float", {base: __.xsd()+"integer" }); | |
546 jOWL.Ontology.Datatype(__.xsd()+"double", {base: __.xsd()+"integer" }); | |
547 jOWL.Ontology.Datatype(__.xsd()+"negativeInteger", {base: __.xsd()+"integer", assert : function(x){ return x < 0;} }); | |
548 jOWL.Ontology.Datatype(__.xsd()+"nonNegativeInteger", {base: __.xsd()+"integer", assert : function(x){ return x >= 0;} }); | |
549 jOWL.Ontology.Datatype(__.xsd()+"nonPositiveInteger", {base: __.xsd()+"integer", assert : function(x){ return x <= 0;} }); | |
550 jOWL.Ontology.Datatype(__.xsd()+"string"); | |
551 | |
552 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; | |
553 | |
554 jOWL.Ontology.Datatype(__.xsd()+"anyURI", {base: __.xsd()+"string", pattern : URIPattern }); | |
555 jOWL.Ontology.Datatype(__.xsd()+"boolean", {sanitize : function(x){ | |
556 if(typeof x == 'boolean'){ return x;} | |
557 if(x == 'true'){ return true;} | |
558 if(x == 'false'){ return false;} | |
559 }, assert : function(x){ | |
560 return typeof x == 'boolean'; | |
561 }, match: function(a, b){ | |
562 if(a === "false"){ a = false;} | |
563 if(a === "true"){ a = true;} | |
564 return (a === b); | |
565 }}); | |
566 | |
567 /** 'superclass' for Properties */ | |
568 jOWL.Ontology.Property = function(jnode){ | |
569 var r = this.parseProperty(jnode); | |
570 if(r){ return r;} | |
571 }; | |
572 | |
573 jOWL.Ontology.Property.prototype = $.extend({}, jOWL.Ontology.Thing.prototype,{ | |
574 isProperty : true, | |
575 parseProperty : function(jnode){ | |
576 if(!jnode || typeof jnode == 'string'){ | |
577 this.domain = this.range = null; | |
578 this.parse(jnode); | |
579 return; | |
580 } | |
581 if(jOWL.options.cacheProperties && jOWL.indices.IDs){ | |
582 var res = jnode.RDF_ID() || jnode.RDF_About(); | |
583 var c = jOWL.index('property').get(res); | |
584 if(c){ return c;} | |
585 } | |
586 this.parse(jnode); | |
587 this.domain= $(this.jnode.get(0).selectSingleNode(__.rdfs('domain'))).RDF_Resource(); | |
588 this.range = $(this.jnode.get(0).selectSingleNode(__.rdfs('range'))).RDF_Resource(); | |
589 } | |
590 }); | |
591 | |
592 /** access to Datatype properties */ | |
593 jOWL.Ontology.DatatypeProperty = function(jnode){ | |
594 var r = this.parseProperty(jnode); | |
595 if(r){ return r;} | |
596 if(this.type == __.owl("AnnotationProperty")){ this.range = __.xsd()+"string";} | |
597 }; | |
598 | |
599 jOWL.Ontology.DatatypeProperty.prototype = $.extend({}, jOWL.Ontology.Thing.prototype, jOWL.Ontology.Property.prototype, { | |
600 isDatatypeProperty : true, | |
601 /** check datatype values against this */ | |
602 assert : function(targetValue, value){ | |
603 var self = this; | |
604 var dt = jOWL.Ontology.Datatype[this.range]; | |
605 if(!dt){ | |
606 console.log(this.range+" datatype reasoning not implemented"); | |
607 return true; | |
608 } | |
609 if(value === undefined){ return dt.assert(targetValue);} | |
610 else {return dt.match(value, targetValue);} | |
611 } | |
612 }); | |
613 | |
614 /** access to Object properties */ | |
615 jOWL.Ontology.ObjectProperty = function(jnode){ | |
616 var r = this.parseProperty(jnode); | |
617 if(r){ return r;} | |
618 var self = this; | |
619 jOWL.Xpath(__.rdf('type'), this.jnode).each(function(){ | |
620 if($(this).RDF_Resource() == __.owl()+"TransitiveProperty"){ self.isTransitive = true;} | |
621 }); | |
622 if(this.jnode.get(0).nodeName == __.owl("TransitiveProperty")){ self.isTransitive = true;} | |
623 }; | |
624 | |
625 jOWL.Ontology.ObjectProperty.prototype = $.extend({}, jOWL.Ontology.Thing.prototype, jOWL.Ontology.Property.prototype, { | |
626 isObjectProperty : true | |
627 }); | |
628 | |
629 /** access to an owl:Class */ | |
630 jOWL.Ontology.Class = function(jnode){ | |
631 this.parse(jnode); | |
632 }; | |
633 | |
634 /** @return jOWL Array of Restrictions */ | |
635 jOWL.Xpath.restrictions = function(jnode){ | |
636 var result = new jOWL.Ontology.Array(); | |
637 jOWL.Xpath(__.rdfs("subClassOf")+"/"+__.owl("Restriction"), jnode) | |
638 .add(jOWL.Xpath(__.owl("intersectionOf")+"/"+__.owl("Restriction"), jnode)) | |
639 .each(function(){ | |
640 result.push(new jOWL.Ontology.Restriction($(this))); | |
641 }); | |
642 return result; | |
643 }; | |
644 | |
645 /** Internal Use */ | |
646 jOWL.Ontology.Intersection = function(jnode){ | |
647 var self = this; | |
648 this.jnode = jnode; | |
649 this._arr = []; | |
650 this.URI = this.jnode.parent().RDF_ID(); | |
651 this.matches = {}; | |
652 jOWL.Xpath(__.owl("Restriction"), jnode).each(function(){ | |
653 var restr = new jOWL.Ontology.Restriction($(this)); | |
654 if(restr.isValueRestriction){self._arr.push(restr);} | |
655 }); | |
656 jOWL.Xpath(__.owl('Class'), jnode).each(function(){ | |
657 var uri = $(this).RDF_About(); | |
658 if(uri){ self._arr.push(jOWL(uri));} | |
659 }); | |
660 }; | |
661 | |
662 jOWL.Ontology.Intersection.prototype = { | |
663 isIntersection : true, | |
664 jOWL : jOWL.version, | |
665 match : function(id, cls, clRestr){ | |
666 if(id == this.URI){ return false;} | |
667 if(this.matches[id] !== undefined){ return this.matches[id]; }//local cache | |
668 | |
669 for(var i =0;i<this._arr.length;i++){ | |
670 var entry = this._arr[i]; | |
671 var m = false; | |
672 if(entry.isRestriction){ | |
673 clRestr.each(function(){ | |
674 if(this.equals(entry)){ m = true; return false;} | |
675 }); | |
676 if(!m) { | |
677 this.matches[id] = false; | |
678 return false; | |
679 } | |
680 } else if(entry.isClass){ | |
681 for(var j = 0;j<cls.length;j++){ | |
682 if(entry.equals(cls[j])){m = true; break;} | |
683 var it = jOWL.index('ID')[cls[j]]; | |
684 if(it){ | |
685 var narr = jOWL.Xpath.classes(jOWL.index('ID')[cls[j]].jnode); | |
686 for (var z=0;z<narr.length ; z++){ | |
687 if(entry.equals(narr[z])){m = true; break;} | |
688 } | |
689 } | |
690 } | |
691 if(!m){ | |
692 this.matches[id] = false; | |
693 return false; | |
694 } | |
695 } | |
696 } | |
697 this.matches[id] = true; | |
698 return this.matches[id]; | |
699 }, | |
700 equals : function(isect){ | |
701 if(!isect.isIntersection){ return false;} | |
702 for(var i =0;i<this._arr.length;i++){ | |
703 var match = false; | |
704 for(var j = 0;j<isect._arr.length;j++){ | |
705 if(isect._arr[j].equals(this._arr[i])){ match = true;} | |
706 } | |
707 if(!match){ return false;} | |
708 } | |
709 return true; | |
710 } | |
711 }; | |
712 | |
713 jOWL.Ontology.Class.prototype = $.extend({}, jOWL.Ontology.Thing.prototype, { | |
714 isClass : true, | |
715 /** @return A jOWL.Ontology.Array of individuals for this class & its subclasses */ | |
716 individuals : function(){ | |
717 var arr = new jOWL.Ontology.Array(); | |
718 var q = new jOWL.SPARQL_DL("Type(?x, "+this.name+")").execute({async: false, onComplete: function(r){ arr = r.jOWLArray("?x");} }); | |
719 return arr; | |
720 }, | |
721 /** @return A jOWL.Ontology.Array of individuals (if oneOf list) */ | |
722 oneOf : function(){ | |
723 var arr = new jOWL.Ontology.Array(); | |
724 var oneOf = this.jnode.children().filter(function(){return this.tagName == __.owl("oneOf");}); | |
725 oneOf.children().each(function(){ | |
726 arr.push(jOWL($(this).RDF_About())); | |
727 }); | |
728 return arr; | |
729 }, | |
730 /** @return A jOWL.Ontology.Array of direct children */ | |
731 children : function(){ | |
732 var that = this; | |
733 var oChildren = jOWL.data(this.name, "children"); | |
734 if(oChildren){ return oChildren;} | |
735 oChildren = new jOWL.Ontology.Array(); | |
736 if(this.oneOf().length){return oChildren;} | |
737 var URI = this.URI; | |
738 | |
739 for(x in jOWL.index('ID')){ | |
740 if(x === this.URI){ continue;} | |
741 var node = jOWL.index('ID')[x]; | |
742 if(!node.isClass){continue;} | |
743 var cls = jOWL.Xpath.classes(node.jnode); //direct subClasses | |
744 for(var i=0;i<cls.length;i++){ | |
745 if(this.equals(cls[i])){ | |
746 oChildren.push(node); | |
747 } | |
748 } | |
749 var clRestr = jOWL.Xpath.restrictions(node.jnode); | |
750 var intersections = jOWL.index("intersection")[URI]; | |
751 if(intersections){ | |
752 intersections.each(function(){//fully defined Subclasses | |
753 if(this.match(x, cls, clRestr)){oChildren.push(node);} | |
754 }); | |
755 } | |
756 } | |
757 //an ObjectProperty mentions this as domain | |
758 jOWL.index("property").each(function(){ | |
759 if(this.domain == that.name){ | |
760 var nodes = jOWL.Xpath('//'+__.owl('onProperty')+'[@'+__.rdf('resource')+'="#'+this.name+'"]/parent::'+__.owl('Restriction')+'/..'); | |
761 nodes.filter(function(){ return (this.nodeName == __.owl('intersectionOf') || this.nodeName == __.rdfs('subClassOf')); | |
762 }).each(function(){ | |
763 var cl = jOWL($(this.selectSingleNode('parent::'+__.owl('Class')))); | |
764 if(!oChildren.contains(cl) && cl.name != that.name && cl.name !== undefined){ oChildren.push(cl);} | |
765 }); | |
766 } | |
767 }); | |
768 //filter out redundancies | |
769 oChildren.filter(function(){ | |
770 this.hierarchy(false); | |
771 return (this.parents().contains(URI)); | |
772 }); | |
773 jOWL.data(this.name, "children", oChildren); | |
774 return oChildren; | |
775 }, | |
776 setParents : function(parents){ | |
777 jOWL.data(this.name, "parents", parents); return parents; | |
778 }, | |
779 /** @return A jOWL.Ontology.Array of parents, includes redundancies, to exclude do a hierarchy search first.*/ | |
780 parents : function(){ | |
781 var self = this; | |
782 var oParents = jOWL.data(this.name, "parents"); | |
783 if(oParents){ return oParents;} | |
784 | |
785 var temp = []; | |
786 | |
787 var cls = jOWL.Xpath.classes(this.jnode); | |
788 for(var i=0;i<cls.length;i++){ jOWL.priv.Array.pushUnique(temp, cls[i]);} | |
789 | |
790 var restr = jOWL.Xpath.restrictions(this.jnode); | |
791 restr.each(function(){ | |
792 if(this.property.domain && this.property.domain != self.name){ jOWL.priv.Array.pushUnique(temp, this.property.domain); | |
793 } | |
794 }); | |
795 | |
796 var iSectLoop = function(){ | |
797 if(this.match(self.URI, cls, restr)){ | |
798 jOWL.priv.Array.pushUnique(temp, this.URI); | |
799 } | |
800 | |
801 }; | |
802 | |
803 if(jOWL.options.reason){ | |
804 for(resource in jOWL.index('intersection')){ | |
805 jOWL.index('intersection')[resource].each(iSectLoop); | |
806 } | |
807 } | |
808 | |
809 oParents = new jOWL.Ontology.Array( jOWL.getXML(temp), true); | |
810 if(!oParents.length){ oParents.push(jOWL('Thing'));} | |
811 else if(oParents.length > 1){ oParents.filter(function(){return this.name != ('Thing');});} //Remove Thing reference if other parents exist | |
812 jOWL.data(this.name, "parents", oParents); | |
813 return oParents; | |
814 }, | |
815 /** @return ancestors to the class in a jOWL.Ontology.Array */ | |
816 ancestors : function(){ | |
817 return this.hierarchy(false).flatindex; | |
818 }, | |
819 /** | |
820 Constructs the entire (parent) hierarchy for a class | |
821 @return a jOWL.Ontology.Array containing top nodes (classes directly subsumed by 'owl:Thing') | |
822 @param addInverse add a variable invParents (jOWL.Ontology.Array of child references) to each node with exception of the leaves (original concept) | |
823 */ | |
824 hierarchy : function(addInverse){ | |
825 var endNodes = new jOWL.Ontology.Array(); | |
826 var self = this; | |
827 endNodes.flatindex = new jOWL.Ontology.Array(); | |
828 | |
829 function URIARR(p_arr, obj){ | |
830 var add = true; | |
831 if(!obj){ obj = {}; add = false;} | |
832 if(p_arr.each){ | |
833 p_arr.each(function(){ | |
834 if(obj[this.URI]){return;} | |
835 if(this.URI == __.owl()+'Thing'){ return;} | |
836 if(add){ obj[this.URI] = true;} | |
837 if(this.parents){ URIARR(this.parents(), obj);} | |
838 }); | |
839 } | |
840 return obj; | |
841 } | |
842 | |
843 function traverse(concept){ | |
844 var parents = concept.parents(); | |
845 if(parents.length == 1 && parents.contains(__.owl()+'Thing')){ endNodes.pushUnique(concept); return;} | |
846 else | |
847 { | |
848 var asso = jOWL.options.reason ? URIARR(parents) : {}; | |
849 parents.filter(function(){ return (!asso[this.URI]);}); //throw out redundancies | |
850 parents.each(function(){ | |
851 var item = endNodes.flatindex.pushUnique(this); | |
852 if(addInverse){ | |
853 if(!item.invParents){ item.invParents = new jOWL.Ontology.Array();} | |
854 item.invParents.pushUnique(concept); | |
855 } | |
856 traverse(item); | |
857 }); | |
858 concept.setParents(parents); | |
859 } | |
860 } | |
861 | |
862 traverse(this); | |
863 return endNodes; | |
864 | |
865 }, | |
866 /** | |
867 @param level depth to fetch children, Default 5 | |
868 @return jOWL array of classes that are descendant | |
869 */ | |
870 descendants : function(level){ | |
871 level = (typeof level == 'number') ? level : 5; | |
872 var oDescendants = jOWL.data(this.name, "descendants"); | |
873 if(oDescendants && oDescendants.level >= level){ return oDescendants;} | |
874 oDescendants = new jOWL.Ontology.Array(); | |
875 oDescendants.level = level; | |
876 | |
877 function descend(concept, i){ | |
878 if(i <= level){ | |
879 i++; | |
880 var ch = concept.children(); | |
881 oDescendants.concat(ch); | |
882 ch.each(function(item){ descend(item, i);}); | |
883 } | |
884 } | |
885 | |
886 descend(this, 1); | |
887 jOWL.data(this.name, "descendants", oDescendants); | |
888 return oDescendants; | |
889 }, | |
890 /** @return jOWL.Array of Restrictions, target is an individual, not a class or undefined (unless includeAll is specified) - deprecated */ | |
891 valueRestrictions : function(includeAll, array){ | |
892 return this.sourceof(null, null, {ignoreClasses : !includeAll}); | |
893 }, | |
894 /** | |
895 get all restrictions that satisfy the arguments | |
896 @param property property or array of properties, or null | |
897 @param target class, individuals of array of them, or null | |
898 @return jOWL.Array of Restrictions | |
899 */ | |
900 sourceof : function(property, target, options){ | |
901 options = $.extend({ | |
902 inherited : true, // add restrictions specified on parents as well | |
903 transitive : true, //expand on transitive relations too | |
904 ignoreGenerics : true, //if a parent has an identical property, with another target 'Thing', skip that restriction | |
905 ignoreClasses : false, //only individuals should return | |
906 valuesOnly : true //do not return valueless criteria | |
907 }, options); | |
908 var self = this; | |
909 var crit = jOWL.data(this.name, "sourceof"); | |
910 var jnode = this.jnode; | |
911 | |
912 if(!crit){ | |
913 crit = new jOWL.Ontology.Array(); | |
914 var arr = jOWL.Xpath(__.rdfs("subClassOf")+"/"+__.owl("Restriction"), jnode) | |
915 .add(jOWL.Xpath(__.owl("intersectionOf")+"/"+__.owl("Restriction"), jnode)); | |
916 arr.each(function(index, entry){ | |
917 var cr = new jOWL.Ontology.Restriction($(entry)); | |
918 var dupe = false; | |
919 crit.each(function(item, i){ | |
920 if(this.property.name == cr.property.name){ dupe = item;} | |
921 }); | |
922 if(dupe){ if(!dupe.merge(cr)){ crit.push(cr);} } | |
923 else { crit.push(cr);} | |
924 }); | |
925 jOWL.data(self.name, "sourceof", crit); | |
926 } | |
927 var results = new jOWL.Ontology.Array(); | |
928 | |
929 crit.each(function(){ | |
930 | |
931 var propertyMatch = property ? false : true; | |
932 var targetMatch = target ? false : true; | |
933 | |
934 if(!propertyMatch){ | |
935 if(property.isArray){ propertyMatch = property.contains(this.property);} | |
936 else { propertyMatch = (property.URI == this.property.URI);} | |
937 } | |
938 | |
939 if(!target){ | |
940 if(options.transitive && this.property.isTransitive){ | |
941 var rTarget = this.getTarget(); | |
942 var transitives = rTarget.sourceof(this.property, null, options); | |
943 results.concat(transitives); | |
944 } | |
945 } | |
946 | |
947 if(!targetMatch && !this.target){ | |
948 targetMatch = !options.valuesOnly; | |
949 } | |
950 | |
951 if(!targetMatch){ | |
952 var targ = this.getTarget(); | |
953 if(targ.isClass && options.ignoreClasses){ return;} | |
954 targetMatch = jOWL.priv.testObjectTarget(target, this.target); | |
955 if(!targetMatch && options.transitive && propertyMatch && this.property.isTransitive){ | |
956 if(targ.isThing){ | |
957 if(targ.sourceof(property, target).length){ targetMatch = true;} | |
958 } | |
959 } | |
960 } | |
961 | |
962 if(propertyMatch && targetMatch){ results.pushUnique(this);} | |
963 }); | |
964 | |
965 if(!options.inherited){ return results;} | |
966 | |
967 this.parents().each(function(){ | |
968 if(this.sourceof){ | |
969 this.sourceof(property, target, options).each(function(parentsource){ | |
970 var ptarget = this.getTarget(); | |
971 var containsProperty = false; | |
972 var tempArray = new jOWL.Ontology.Array(); | |
973 results.filter(function(){ | |
974 var restr = this, keep = true; | |
975 if(restr.property.URI == parentsource.property.URI){ | |
976 containsProperty = true; | |
977 if(!options.ignoreGenerics){ | |
978 if(parentsource.target != restr.target){ tempArray.push(parentsource);} | |
979 } else { | |
980 if(ptarget.isThing){ | |
981 keep = restr.getTarget().isThing && parentsource.target != restr.target; | |
982 tempArray.push(parentsource); | |
983 } | |
984 } | |
985 } | |
986 return keep; | |
987 }); | |
988 if(!containsProperty){ results.push(parentsource);} | |
989 results.concat(tempArray); | |
990 }); | |
991 } | |
992 }); | |
993 return results; | |
994 } | |
995 }); | |
996 | |
997 /** Utility object */ | |
998 jOWL.Ontology.Array = function(arr, isXML){ | |
999 var self = this; | |
1000 this.items = []; | |
1001 if(arr){ | |
1002 if(isXML){ $.each(arr, function(){ | |
1003 var entry = this.jOWL ? this : jOWL($(this)); | |
1004 self.items.push(entry);}); | |
1005 } | |
1006 else { this.items = arr;} | |
1007 } | |
1008 this.length = this.items.length; | |
1009 }; | |
1010 | |
1011 jOWL.Ontology.Array.prototype = { | |
1012 jOWL : jOWL.version, | |
1013 isArray : true, | |
1014 bind : function(listitem, fn){ | |
1015 return this.map(function(){ | |
1016 var syntax = listitem ? listitem.clone(true) : $('<span/>'); | |
1017 var html = this.bind(syntax).append(document.createTextNode(' ')); | |
1018 if(fn){ fn.call(html, html, this);} | |
1019 return html.get(0); | |
1020 }); | |
1021 }, | |
1022 concat : function(arr, ignoreUnique){ | |
1023 var self = this; | |
1024 if(arr.each){ arr.each(function(){ | |
1025 if(ignoreUnique){ self.push(this); } | |
1026 else { self.pushUnique(this); } | |
1027 }); | |
1028 } | |
1029 else { self.items = self.items.concat(arr.items); this.length = self.items.length;} | |
1030 return this; | |
1031 }, | |
1032 contains : function(o){ | |
1033 return this.get(o) ? true: false; | |
1034 }, | |
1035 each : function(fn, reverse){ | |
1036 var i, self = this; | |
1037 var stop = false; | |
1038 if(reverse){ | |
1039 for(i=this.items.length - 1; i>=0;i--){ | |
1040 if(stop){ break;} | |
1041 (function(){ | |
1042 var item = self.eq(i); | |
1043 if(fn.call(item, item, i) === false){ stop = true;} | |
1044 })(); | |
1045 } | |
1046 } | |
1047 else { | |
1048 for(i=0;i<this.items.length;i++){ | |
1049 if(stop){ break;} | |
1050 (function(){ | |
1051 var item = self.eq(i); | |
1052 if(fn.call(item, item, i) === false){ stop = true;} | |
1053 })();} | |
1054 } | |
1055 return this; | |
1056 }, | |
1057 eq : function(index){ | |
1058 if(index < 0 || index > this.items.length -1){ return null;} | |
1059 return this.items[index]; | |
1060 }, | |
1061 filter : function(fn){ | |
1062 var self = this; | |
1063 this.each(function(item, i){ | |
1064 var q = fn.call(item, item, i); | |
1065 if(!q){ self.items.splice(i, 1);} | |
1066 }, true); | |
1067 this.length = this.items.length; | |
1068 return this; | |
1069 }, | |
1070 getIndex : function(o){ | |
1071 var found = -1; | |
1072 if(o.equals){ | |
1073 this.each(function(a, i){ | |
1074 if(this.equals && this.equals(o)){ found = i; return false;} | |
1075 }); | |
1076 } | |
1077 else { | |
1078 if(typeof o == 'number'){ return o;} | |
1079 var name = typeof o == "string" ? o : o.name; | |
1080 var URI = o.URI || name; | |
1081 | |
1082 this.each(function(a, i){ | |
1083 if(this.URI){ if(this.URI == URI){ found = i;}} | |
1084 else if(this.name == name){ found = i;} | |
1085 }); | |
1086 } | |
1087 return found; | |
1088 }, | |
1089 get : function(o){ | |
1090 return this.eq(this.getIndex(o)); | |
1091 }, | |
1092 map : function(fn){ | |
1093 var arr = []; | |
1094 this.each(function(){ arr.push(fn.call(this, this));}); | |
1095 return arr; | |
1096 }, | |
1097 push : function(o){ | |
1098 this.items.push(o); | |
1099 this.length = this.items.length; | |
1100 return this; | |
1101 }, | |
1102 pushUnique : function(o){ | |
1103 return this.get(o) || this.push(o).get(o); | |
1104 }, | |
1105 toString : function(){ | |
1106 return this.map(function(){return this.URI;}).join(', '); | |
1107 }, | |
1108 /** Convert this array into an associative array with key = URI */ | |
1109 associative : function(){ | |
1110 var arr = {}; | |
1111 this.each(function(){ | |
1112 if(this.URI){ arr[this.URI] = this;} | |
1113 }); | |
1114 return arr; | |
1115 } | |
1116 }; | |
1117 | |
1118 | |
1119 jOWL.options = {reason: true, locale:false, defaultlocale: 'en', | |
1120 dictionary : { create: true, addID : true }, | |
1121 onParseError : function(msg){alert("jOWL parseError: "+msg);}, cacheProperties : true, niceClassLabels : true}; | |
1122 jOWL.document = null; | |
1123 jOWL.namespace = null; | |
1124 jOWL.indices = { //internal indices | |
1125 P : null, //jOWL array | |
1126 data : {}, | |
1127 IDs : null, | |
1128 I : null, //Intersection | |
1129 T : null, //Thing | |
1130 D : null, //dictionary | |
1131 reset : function(){var i = jOWL.indices; i.data = {}; i.P = null; i.T = null; i.IDs = null; i.I = null;i.D = null;} | |
1132 }; | |
1133 | |
1134 jOWL.index = function(type, wipe){ | |
1135 var i = jOWL.indices; | |
1136 switch (type) | |
1137 { | |
1138 /**jOWL indexes all elements with rdf:ID, and first order ontology elements specified with rdf:about | |
1139 @return Associative array with key = URI and value = jOWL object. | |
1140 */ | |
1141 case "ID": | |
1142 if(i.IDs === null || wipe){ | |
1143 if(wipe){ i.reset();} | |
1144 i.IDs = {}; | |
1145 i.T = {}; | |
1146 var start = new Date(); | |
1147 | |
1148 var rID = jOWL.Xpath("//*[@"+__.rdf("ID")+"]").each(function(){ | |
1149 var jowl = jOWL.getResource($(this)); | |
1150 if(jowl){ | |
1151 i.IDs[jowl.URI] = jowl; | |
1152 if(jowl.isThing){ | |
1153 if(!i.T[jowl.Class]){ i.T[jowl.Class] = new jOWL.Ontology.Array();} | |
1154 i.T[jowl.Class].push(jowl); | |
1155 } | |
1156 } | |
1157 }); | |
1158 | |
1159 var rAbout = jOWL.Xpath("/"+__.rdf("RDF")+"/*[@"+__.rdf("about")+"]").each(function(){ | |
1160 var jnode = $(this); | |
1161 var jowl = jOWL.getResource($(this)); | |
1162 if(!jowl){ return;} | |
1163 if(jowl.isClass || jowl.isProperty || jowl.isThing){ | |
1164 if(i.IDs[jowl.URI]){ jnode.children().appendTo(i.IDs[jowl.URI].jnode); return;} | |
1165 i.IDs[jowl.URI] = jowl; | |
1166 if(jowl.isThing){ | |
1167 if(!i.T[jowl.Class]){ i.T[jowl.Class] = new jOWL.Ontology.Array();} | |
1168 i.T[jowl.Class].push(jowl); | |
1169 } | |
1170 return; | |
1171 } | |
1172 }); | |
1173 console.log("Loaded in "+(new Date().getTime() - start.getTime())+"ms"); | |
1174 } | |
1175 return i.IDs; | |
1176 /** Generated together with ID index. | |
1177 * @return Associative Array, key = class, value = jOWL Array of individuals. | |
1178 */ | |
1179 case "Thing": | |
1180 return i.T; | |
1181 case "intersection": | |
1182 if(i.I === null || wipe){ | |
1183 var temp = new jOWL.Ontology.Array(); | |
1184 i.I = {}; | |
1185 jOWL.Xpath("//"+__.owl("intersectionOf")).each(function(){ | |
1186 var isect = new jOWL.Ontology.Intersection($(this)); | |
1187 if(!isect.URI){return;} | |
1188 var dupe = temp.get(isect); | |
1189 if(dupe){ | |
1190 console.log("duplicate intersection found between : (Ignoring) "+isect.URI+" and "+dupe.URI); | |
1191 } else { | |
1192 if(!i.I[isect.URI]){i.I[isect.URI] = new jOWL.Ontology.Array();} | |
1193 temp.push(isect); | |
1194 i.I[isect.URI].push(isect); | |
1195 } | |
1196 }); | |
1197 } | |
1198 return i.I; | |
1199 case "property": | |
1200 if(i.P === null || wipe) | |
1201 { | |
1202 jOWL.options.cacheProperties = false; | |
1203 i.P = new jOWL.Ontology.Array(); | |
1204 for(x in i.IDs){ | |
1205 var jowl = i.IDs[x]; | |
1206 if(jowl.isProperty){ i.P.push(jowl);} | |
1207 } | |
1208 jOWL.options.cacheProperties = true; | |
1209 } | |
1210 return i.P; | |
1211 case "dictionary": | |
1212 /**Dictionary: Array of Arrays, where secondary array is of form: [0] = term, [1] = rdfID, [2] = locale */ | |
1213 if(i.D === null || wipe) | |
1214 { | |
1215 i.D = []; | |
1216 for(x in i.IDs){ | |
1217 var entry = i.IDs[x]; | |
1218 i.D = i.D.concat(entry.terms()); | |
1219 } | |
1220 } | |
1221 return i.D; | |
1222 } | |
1223 }; | |
1224 | |
1225 /** Internal Function, storing data in associative array (JSON), | |
1226 jquery data function cannot be used as expando data does not work in IE for ActiveX XMLhttprequest*/ | |
1227 jOWL.data = function(rdfID, dtype, data){ | |
1228 var d = jOWL.indices.data; | |
1229 if(!d[rdfID]){ d[rdfID] = {};} | |
1230 if(!data){ return d[rdfID][dtype];} | |
1231 d[rdfID][dtype] = data; | |
1232 }; | |
1233 | |
1234 /** | |
1235 * Initialize jOWL with an OWL-RDFS document. | |
1236 * @param path relative path to xml document | |
1237 * @param callback callback function to be called when loaded. | |
1238 * @options : optional settings: | |
1239 * onParseError : function(msg){} function to ba called when parsing fails | |
1240 * reason : true/false, turns on additional reasoning at the expense of performance | |
1241 * locale: set preferred language (if available), examples en, fr... | |
1242 */ | |
1243 jOWL.load = function(path, callback, options){ | |
1244 var that = this; | |
1245 if($.browser.msie && location.toString().indexOf('file') === 0){ //IE won't load local xml files otherwise | |
1246 var xml = document.createElement("xml"); | |
1247 xml.validateOnParse = false; //IE throws DTD errors (for 'rdf:') on perfectly defined OWL files otherwise | |
1248 xml.src = path; | |
1249 xml.onreadystatechange = function(){ | |
1250 if(xml.readyState == "interactive"){ var xmldoc = xml.XMLDocument; document.body.removeChild(xml);callback(that.parse(xmldoc, options));} | |
1251 }; | |
1252 document.body.appendChild(xml); | |
1253 } | |
1254 else { | |
1255 $.get(path, function(xml){callback(that.parse(xml, options));}); | |
1256 } | |
1257 }; | |
1258 | |
1259 /** | |
1260 * initialize jOWL with some OWL-RDFS syntax | |
1261 * @param doc Either an xmlString or an xmlDocument | |
1262 * @param options optional, onParseError(msg) : function to execute when parse fails | |
1263 * @returns false on failure, or the jOWL object | |
1264 */ | |
1265 jOWL.parse = function(doc, options){ | |
1266 jOWL.document = null; | |
1267 this.options = $.extend(jOWL.options, options); | |
1268 if(typeof doc == 'string'){ doc = jOWL.fromString(doc);} | |
1269 jOWL.document = doc; | |
1270 if($.browser.msie){ | |
1271 if(doc.parseError.errorCode !== 0){ jOWL.options.onParseError(doc.parseError.reason); return false;} | |
1272 } | |
1273 else if(doc.documentElement.nodeName == 'parsererror'){jOWL.options.onParseError(doc.documentElement.firstChild.nodeValue); return false;} | |
1274 var root = $(doc.documentElement); | |
1275 jOWL.NS(root); | |
1276 if($.browser.msie){ | |
1277 jOWL.document.setProperty("SelectionLanguage", "XPath"); | |
1278 jOWL.document.setProperty("SelectionNamespaces", __()); | |
1279 } | |
1280 this.index('ID', true); | |
1281 if(jOWL.options.cacheProperties){ this.index('property', true);} | |
1282 if(jOWL.options.dictionary.create){ jOWL.index("dictionary");} | |
1283 jOWL.Thing = new jOWL.Ontology.Thing($(jOWL.create(__.owl, "Class").attr(__.rdf, 'about', __.owl()+'Thing').node)); | |
1284 jOWL.Thing.type = false; | |
1285 return this; | |
1286 }; | |
1287 | |
1288 /** | |
1289 * A String representation of the OWL-RDFS document | |
1290 * @param xmlNode optional, node to generate a string from, when unspecified the entire document | |
1291 */ | |
1292 jOWL.toString = function(xmlNode){ | |
1293 if(!xmlNode){ return jOWL.toString(jOWL.document);} | |
1294 if($.browser.msie){ return xmlNode.xml;} | |
1295 return new XMLSerializer().serializeToString(xmlNode);// Gecko-based browsers, Safari, Opera. | |
1296 }; | |
1297 | |
1298 /** create a document from string */ | |
1299 jOWL.fromString = function(doc){ | |
1300 var owldoc; | |
1301 if(document.implementation.createDocument){ owldoc = new DOMParser().parseFromString(doc, "text/xml");} // Mozilla and Netscape browsers | |
1302 else if(window.ActiveXObject){ // MSIE | |
1303 var xmldoc = new ActiveXObject("Microsoft.XMLDOM"); | |
1304 xmldoc.async="false"; | |
1305 xmldoc.validateOnParse = false; | |
1306 xmldoc.loadXML(doc); | |
1307 owldoc = xmldoc; | |
1308 } | |
1309 return owldoc; | |
1310 }; | |
1311 | |
1312 /** @return false if belongs to this namespace, or an array with length two, arr[0] == url, arr[1] == id */ | |
1313 jOWL.isExternal = function(resource){ | |
1314 var r = jOWL.resolveURI(resource, true); | |
1315 return r[0] != jOWL.namespace ? r : false; | |
1316 }; | |
1317 | |
1318 /** | |
1319 if a URI belongs to the loaded namespace, then strips the prefix url of, else preserves URI | |
1320 also able to parse and reference html (or jquery) elements for their URI. | |
1321 */ | |
1322 jOWL.resolveURI = function(URI, array){ | |
1323 if(typeof URI != "string"){ | |
1324 var node = URI.jquery ? URI.get(0) : URI; | |
1325 URI = node.localName || node.baseName; | |
1326 if(node.namespaceURI){ URI = node.namespaceURI + URI;} | |
1327 return jOWL.resolveURI(URI, array); | |
1328 } | |
1329 var rs = URI, ns = jOWL.namespace; | |
1330 if(URI.indexOf('http') === 0){ | |
1331 var tr = URI.indexOf('#'); | |
1332 if(tr <= 0){ tr = URI.lastIndexOf('/');} | |
1333 if(tr > 0) | |
1334 { | |
1335 ns = URI.substring(0, tr+1); | |
1336 rs = URI.substring(tr+1); | |
1337 } | |
1338 } else if(URI.charAt(0) == '#'){ return URI.substring(1);} | |
1339 if(array){ return [ns, rs];} | |
1340 if(ns == jOWL.namespace){ return rs;} | |
1341 return URI; | |
1342 }; | |
1343 | |
1344 /** | |
1345 Main method to get an Ontology Object, access via jOWL(>String>, options); | |
1346 resource: rdfID/rdfResource<String> or jQuery node. | |
1347 */ | |
1348 jOWL.getResource = function(resource, options){ | |
1349 if(!jOWL.document){ throw "You must successfully load an ontology before you can find anything";} | |
1350 if(!resource){ throw "No resource specified";} | |
1351 var node; | |
1352 var opts = $.extend({}, options); | |
1353 if(typeof resource == 'string'){ | |
1354 resource = jOWL.resolveURI(resource); | |
1355 if(resource == 'Thing' || resource == __.owl()+'Thing'){ return jOWL.Thing;} | |
1356 if(opts.type == 'property' && jOWL.options.cacheProperties){ | |
1357 var c = jOWL.index('property').get(resource); | |
1358 if(c){ return c;} | |
1359 if(jOWL.isExternal(resource)){ console.log("undeclared resource: "+resource); return new jOWL.Ontology.Property(resource);} | |
1360 } | |
1361 var match = jOWL.index("ID")[resource]; | |
1362 if(!match){ //try case insensitive | |
1363 for(caseIns in jOWL.index("ID")){ | |
1364 if(caseIns.toLowerCase() == resource.replace(/ /g, "").toLowerCase()){ match = jOWL.index("ID")[caseIns]; break;} | |
1365 } | |
1366 } | |
1367 if(!match){ | |
1368 if(jOWL.isExternal(resource)){ | |
1369 console.log("undeclared resource: "+resource); | |
1370 return new jOWL.Ontology.Thing(resource); | |
1371 } | |
1372 console.log(resource+" not found"); | |
1373 return null; | |
1374 } | |
1375 return match; | |
1376 } | |
1377 node = resource.jquery ? resource : $(resource); | |
1378 var jj = jOWL.type(node); if(!jj){ return null;} | |
1379 return new (jj)(node); | |
1380 }; | |
1381 | |
1382 /** | |
1383 * @param node jquery or html element. | |
1384 * @return the ontology type of the object. | |
1385 */ | |
1386 jOWL.type = function(node){ | |
1387 var xmlNode = node.jquery ? node.get(0) : node; | |
1388 switch(xmlNode.nodeName){ | |
1389 case __.owl("Class") : return jOWL.Ontology.Class; | |
1390 case __.rdfs("Class") : return jOWL.Ontology.Class; //test | |
1391 case __.owl("Ontology") : return jOWL.Ontology; | |
1392 case __.owl("ObjectProperty") : return jOWL.Ontology.ObjectProperty; | |
1393 case __.owl("DatatypeProperty") : return jOWL.Ontology.DatatypeProperty; | |
1394 case __.owl("FunctionalProperty") : return jOWL.Ontology.Property; | |
1395 case __.rdf("Property") : return jOWL.Ontology.Property; | |
1396 case __.owl("InverseFunctionalProperty") : return jOWL.Ontology.ObjectProperty; | |
1397 case __.owl("TransitiveProperty") : return jOWL.Ontology.ObjectProperty; | |
1398 case __.owl("SymmetricProperty") : return jOWL.Ontology.ObjectProperty; | |
1399 //jOWL currently treats annotationproperties as string datatypeproperties. | |
1400 case __.owl("AnnotationProperty") : return jOWL.Ontology.DatatypeProperty; | |
1401 default : | |
1402 switch(xmlNode.namespaceURI){ | |
1403 case __.owl(): if(xmlNode.nodeName == __.owl("Thing") ){ return jOWL.Ontology.Individual;} return false; | |
1404 case __.rdf(): return false; | |
1405 case __.rdfs(): return false; | |
1406 default : return jOWL.Ontology.Individual; | |
1407 } | |
1408 } | |
1409 }; | |
1410 | |
1411 /** | |
1412 @param rdfID <String> or Array<String> | |
1413 @return Array of DOM (xml) Nodes | |
1414 */ | |
1415 jOWL.getXML = function(rdfID){ | |
1416 var node = []; | |
1417 function fetchFromIndex(rdfID){ | |
1418 var el = jOWL.index("ID")[rdfID]; | |
1419 return el ? el : null; | |
1420 } | |
1421 | |
1422 if(typeof rdfID == 'string'){ var q = fetchFromIndex(rdfID); if(q){ node.push(q);} } | |
1423 else if(jOWL.priv.Array.isArray(rdfID)){ //assume an array of string rdfIDs | |
1424 $.each(rdfID, function(){ | |
1425 var el = fetchFromIndex(this); if(el){ node.push(el);} | |
1426 }); | |
1427 } | |
1428 return node; | |
1429 }; | |
1430 | |
1431 /** Create new ontology elements */ | |
1432 jOWL.create = function(namespace, name, document){ | |
1433 var doc = document ? document : jOWL.document; | |
1434 | |
1435 var el = { | |
1436 attr : function(namespace, name, value){ | |
1437 if($.browser.msie){ | |
1438 var attribute = doc.createNode(2, namespace(name), namespace()); | |
1439 attribute.nodeValue = value; | |
1440 this.node.setAttributeNode(attribute); | |
1441 } | |
1442 else { this.node.setAttributeNS(namespace(), namespace(name), value);} | |
1443 return this; | |
1444 }, | |
1445 appendTo : function(node){ | |
1446 var n = node.node ? node.node : node; | |
1447 n.appendChild(this.node); | |
1448 return this; | |
1449 }, | |
1450 text : function(text, cdata){ | |
1451 var txt = cdata ? doc.createCDATASection(text) : doc.createTextNode(text); | |
1452 this.node.appendChild(txt); | |
1453 return this; | |
1454 } | |
1455 }; | |
1456 | |
1457 if($.browser.msie){ el.node = doc.createNode(1, namespace(name), namespace());} | |
1458 else { el.node = doc.createElementNS(namespace(), namespace(name));} | |
1459 return el; | |
1460 }; | |
1461 | |
1462 /** Create a blank ontology document */ | |
1463 jOWL.create.document = function(href){ | |
1464 var owl = []; | |
1465 var base = href || window.location.href+"#"; | |
1466 owl.push('<?xml version="1.0"?>'); | |
1467 owl.push('<'+__.rdf('RDF')+' xml:base="'+base+'" xmlns="'+base+'" '+__()+'>'); | |
1468 owl.push(' <'+__.owl('Ontology')+' '+__.rdf('about')+'=""/>'); | |
1469 owl.push('</'+__.rdf('RDF')+'>'); | |
1470 return jOWL.fromString(owl.join('\n')); | |
1471 }; | |
1472 | |
1473 /** Extracts RDFa syntax from current page and feeds it to jOWL, simple implementation, only classes for the time being */ | |
1474 jOWL.parseRDFa = function(fn, options){ | |
1475 var entries = options.node ? $("[typeof]", options.node) : $("[typeof]"); | |
1476 var doc = jOWL.create.document(); | |
1477 | |
1478 function property(p, node){ | |
1479 var arr = []; | |
1480 $("[property="+p+"]", node).each(function(){ arr.push($(this).attr('content') || $(this).html());}); | |
1481 if(node.attr('property') === p){ arr.push(node.attr('content') || node.html());} | |
1482 return arr; | |
1483 } | |
1484 | |
1485 function rel(p, node){ | |
1486 var arr = []; | |
1487 $("[rel="+p+"]", node).each(function(){ arr.push($(this).attr('resource'));}); | |
1488 if(node.attr("rel") === p){ arr.push(node.attr('resource'));} | |
1489 return arr; | |
1490 } | |
1491 | |
1492 function makeClass(node, ID){ | |
1493 var cl = jOWL.create(__.owl, "Class", doc).attr(__.rdf, 'about', ID).appendTo(doc.documentElement); | |
1494 | |
1495 var parents = property(__.rdfs("subClassOf"), node).concat(rel(__.rdfs("subClassOf"), node)); | |
1496 for(var i = 0;i<parents.length;i++){ | |
1497 var p = jOWL.create(__.rdfs, "subClassOf", doc).attr(__.rdf, "resource", parents[i]).appendTo(cl); | |
1498 } | |
1499 return cl; | |
1500 } | |
1501 | |
1502 entries.each(function(){ | |
1503 var node = $(this); | |
1504 var type = node.attr("typeof"), el; | |
1505 | |
1506 if(type == __.owl("Class")){ el = makeClass(node, jOWL.resolveURI(node.attr("about")));} | |
1507 | |
1508 $.each(property(__.rdfs('comment'), node), function(){ | |
1509 jOWL.create(__.rdfs, "comment", doc).appendTo(el).text(this, true); | |
1510 }); | |
1511 | |
1512 $.each(property(__.rdfs('label'), node), function(){ | |
1513 jOWL.create(__.rdfs, "label", doc).appendTo(el).text(this); | |
1514 }); | |
1515 }); | |
1516 jOWL.parse(doc, options); | |
1517 fn(); | |
1518 }; | |
1519 | |
1520 /** | |
1521 Match part or whole of the rdfResource<String> | |
1522 Used for term searches, intend to (partially) replace it by a sparql-dl query later on | |
1523 options: | |
1524 filter: filter on a specific type, possible values: Class, Thing, ObjectProperty, DatatypeProperty | |
1525 exclude: exclude specific types, not fully implemented | |
1526 */ | |
1527 jOWL.query = function(match, options){ | |
1528 options = $.extend({exclude : false}, options); | |
1529 if(options.filter == 'Class'){ options.filter = __.owl("Class");} | |
1530 var that = this; | |
1531 //filter : [], exclude : false | |
1532 var items = new jOWL.Ontology.Array(); | |
1533 var jsonobj = {}; | |
1534 var test = jOWL.index("dictionary"); | |
1535 | |
1536 function store(item){ | |
1537 var include = false, i = 0; | |
1538 if(options.filter){ | |
1539 if(typeof options.filter == 'string'){ include = (options.filter == item[3]);} | |
1540 else { for(i = 0;i<options.filter.length;i++){ if(options.filter[i] == item[3]){ include = true;} } } | |
1541 } | |
1542 else if(options.exclude){ | |
1543 include = true; | |
1544 if(typeof options.exclude == 'string'){ include = (options.exclude !== item[3]);} | |
1545 else { for(i = 0;i<options.exclude.length;i++){ if(options.exclude[i] == item[3]){ include = false;} } } | |
1546 } | |
1547 else { include = true;} | |
1548 if(!include){ return;} | |
1549 if(!jsonobj[item[1]]){ jsonobj[item[1]] = [];} | |
1550 jsonobj[item[1]].push( { term : item[0], locale: item[2], type: item[3] }); | |
1551 } | |
1552 | |
1553 for(var y = 0;y<test.length;y++){ | |
1554 var item = test[y]; | |
1555 var bool = options.exclude; | |
1556 var r = item[0].searchMatch(match); | |
1557 if(r > -1){ | |
1558 if(options.locale){ if(options.locale == item[2]){ store(item);} } | |
1559 else { store(item);} | |
1560 } | |
1561 } | |
1562 return jsonobj; | |
1563 }; | |
1564 | |
1565 /** | |
1566 allows asynchronous looping over arrays (prevent bowser freezing). | |
1567 arr the array to loop asynchonrously over. | |
1568 options.modify(item) things to do with each item of the array | |
1569 options.onUpdate array the size of chewsize or smaller, containing processed entries | |
1570 options.onComplete(array of results) function triggered when looping has completed | |
1571 */ | |
1572 jOWL.throttle =function(array, options){ | |
1573 options = $.extend({ | |
1574 modify : function(result){}, | |
1575 //onUpdate : function(arr){}, | |
1576 onComplete : function(arr){}, | |
1577 async : true, | |
1578 chewsize : 5, | |
1579 startIndex : 0, | |
1580 timing : 5 | |
1581 }, options); | |
1582 var temp = array.jOWL ? array.items : (array.jquery) ? $.makeArray(array) : array; | |
1583 var items = options.startIndex ? temp.slice(startIndex) : temp.concat(); //clone the array | |
1584 var results = []; | |
1585 | |
1586 (function(){ | |
1587 var count = options.chewsize; | |
1588 var a = []; | |
1589 while (count > 0 && items.length > 0) | |
1590 { | |
1591 var item = items.shift(); count--; | |
1592 var result = options.modify.call(item, item); | |
1593 if(result){ results.push(result); a.push(result);} | |
1594 } | |
1595 if(options.onUpdate){ options.onUpdate(a);} | |
1596 | |
1597 if(items.length> 0){ | |
1598 if(options.async){ setTimeout(arguments.callee, options.timing);} | |
1599 else {arguments.callee();} | |
1600 } | |
1601 else{ options.onComplete(results);} | |
1602 })(); | |
1603 }; | |
1604 | |
1605 /** Creates a new resultobj for the SPARQL-DL functionality */ | |
1606 jOWL.SPARQL_DL_Result = function(){ | |
1607 this.assert = undefined; | |
1608 this.head = {}; //associative array of query parameters, with value jOWL Array of results | |
1609 this.results = []; //sparql-dl bindings | |
1610 this.isBound = false; | |
1611 }; | |
1612 | |
1613 jOWL.SPARQL_DL_Result.prototype = { | |
1614 sort : function(param){ | |
1615 if(!param){ throw "parameter must be defined for sort function";} | |
1616 function sortResults(a, b){ | |
1617 var o = a[param].name || a[param]; | |
1618 var p = b[param].name || b[param]; | |
1619 return (o < p) ? -1 : 1; | |
1620 } | |
1621 if(this.results){ this.results.sort(sortResults); } | |
1622 }, | |
1623 jOWLArray : function(param){ | |
1624 if(!param){ throw "parameter must be defined for jOWLArray function";} | |
1625 var arr = new jOWL.Ontology.Array(); | |
1626 for(var i=0;i<this.results.length;i++){ | |
1627 if(this.results[i][param]){ arr.pushUnique(this.results[i][param]);} | |
1628 } | |
1629 return arr; | |
1630 }, | |
1631 /** Filter head Parameters */ | |
1632 filter : function(param, arr){ | |
1633 if(this.head[param] === undefined){this.head[param] = arr;} | |
1634 else { | |
1635 var self = this; | |
1636 this.head[param].filter(function(){ return (arr.contains(this));}); | |
1637 arr.filter(function(){ return (self.head[param].contains(this));}); | |
1638 } | |
1639 }, | |
1640 /** Update result section, results = SPARQL_DL_Array */ | |
1641 bind : function(results){ | |
1642 if(!this.isBound){//new results | |
1643 this.results = this.results.concat(results.arr); | |
1644 this.isBound = true; | |
1645 return; | |
1646 } | |
1647 var multimapping = -1; | |
1648 for(x in results.mappings){ multimapping++; } | |
1649 var toAdd = []; | |
1650 | |
1651 for(x in results.mappings){ | |
1652 var otherKeys; | |
1653 if(multimapping){ | |
1654 otherKeys = results.keyCentric(x); | |
1655 } | |
1656 for(var i = this.results.length-1;i>=0;i--){ | |
1657 var valueX = this.results[i][x]; | |
1658 if(valueX){ | |
1659 if(!results.mappings[x].contains(valueX)){ | |
1660 this.results.splice(i, 1); | |
1661 continue; | |
1662 } | |
1663 if(multimapping){ | |
1664 var keyArr= otherKeys[valueX.URI]; | |
1665 //ignoring the opposite for now (assuming original key x is unique (limits statements)) | |
1666 //TODO: improve these result merging methods/flexibility | |
1667 for(var oK = 0; oK < keyArr.length;oK++){ | |
1668 var obj = (oK === 0) ? this.results[i] : {}; | |
1669 var valueY = keyArr[oK]; | |
1670 obj[x] = valueX; | |
1671 for(yK in valueY){ obj[yK] = valueY[yK]; } | |
1672 toAdd.push(obj); | |
1673 } | |
1674 this.results.splice(i, 1); | |
1675 } | |
1676 } | |
1677 } | |
1678 } | |
1679 this.results = this.results.concat(toAdd); | |
1680 } | |
1681 }; | |
1682 /** Creates a new query for the SPARQL-DL functionality */ | |
1683 jOWL.SPARQL_DL_Query = function(syntax, parameters){ | |
1684 this.parse(syntax); | |
1685 this.fill(parameters); | |
1686 this.entries = this.entries.sort(this.sort); | |
1687 }; | |
1688 | |
1689 jOWL.SPARQL_DL_Query.prototype = { | |
1690 parse : function(syntax){ | |
1691 var r2 = /(\w+)[(]([^)]+)[)]/; | |
1692 var entries = syntax.match(/(\w+[(][^)]+[)])/g); | |
1693 if(!entries){ this.error = "invalid abstract sparql-dl syntax"; return;} | |
1694 entries = jOWL.priv.Array.unique(entries); | |
1695 for(var i = 0;i<entries.length;i++){ | |
1696 var y = entries[i].match(r2); | |
1697 if(y.length != 3){ this.error = "invalid abstract sparql-dl syntax"; return;} | |
1698 entries[i] = [y[1], y[2].replace(/ /g, "").split(',')]; | |
1699 } | |
1700 this.entries = entries; | |
1701 }, | |
1702 fill : function(parameters){ | |
1703 for(var i = 0;i<this.entries.length;i++){ | |
1704 for(var j =0; j<this.entries[i][1].length; j++){ | |
1705 var p = parameters[this.entries[i][1][j]]; | |
1706 if(p !== undefined) { this.entries[i][1][j] = p;} | |
1707 else { | |
1708 p = this.entries[i][1][j]; | |
1709 if(p.charAt(0) != '?') | |
1710 { | |
1711 if(this.entries[i][0] == "PropertyValue" && j == 2) | |
1712 { | |
1713 var m = p.match(/^["'](.+)["']$/); | |
1714 if(m && m.length == 2){ this.entries[i][1][j] = {test: m[1]}; break;} | |
1715 } | |
1716 this.entries[i][1][j] = jOWL(p); | |
1717 if(this.entries[i][1][j] === null){this.entries.error = "a parameter in the query was not found"; return;} | |
1718 } | |
1719 } | |
1720 } | |
1721 } | |
1722 }, | |
1723 sort : function(a, b){ | |
1724 var i; | |
1725 if(a[1].length == 1){ return (b[0] == 'PropertyValue') ? 1 : -1;} | |
1726 if(b[1].length == 1){ return (a[0] == 'PropertyValue') ? -1 : 1;} | |
1727 var avar = 0; for(i = 0;i<a[1].length;i++){ if(typeof a[1][i] == 'string'){ avar++;} } | |
1728 var bvar = 0; for(i = 0;i<a[1].length;i++){ if(typeof b[1][i] == 'string'){ bvar++;} } | |
1729 if(avar != bvar){ return avar - bvar;} | |
1730 if(a[0] == 'Type' && b[0] != 'Type'){ return -1;} | |
1731 if(a[0] != 'Type' && b[0] == 'Type'){ return 1;} | |
1732 return 0; | |
1733 } | |
1734 }; | |
1735 | |
1736 /** Private function */ | |
1737 function _Binding(bindingarray){ | |
1738 this.value = {}; | |
1739 this.arr = bindingarray; | |
1740 } | |
1741 | |
1742 _Binding.prototype = { | |
1743 bind : function(key, value){ | |
1744 this.value[key] = value; | |
1745 if(!this.arr.mappings[key]){ this.arr.mappings[key] = new jOWL.Ontology.Array();} | |
1746 this.arr.mappings[key].push(value); | |
1747 return this; | |
1748 } | |
1749 }; | |
1750 | |
1751 /** Local Function, private access, Temp results */ | |
1752 function SPARQL_DL_Array(keys){ | |
1753 this.arr = []; | |
1754 this.mappings = {}; | |
1755 | |
1756 if(keys){ | |
1757 for(var i =0;i<keys.length;i++){ | |
1758 if(keys[i]){this.mappings[keys[i]] = new jOWL.Ontology.Array();} | |
1759 } | |
1760 } | |
1761 } | |
1762 | |
1763 SPARQL_DL_Array.prototype = { | |
1764 add : function(binding){ | |
1765 this.arr.push(binding.value); | |
1766 return binding; | |
1767 }, | |
1768 push : function(key, value){ | |
1769 var binding = new _Binding(this); | |
1770 binding.bind(key, value); | |
1771 this.arr.push(binding.value); | |
1772 return binding; | |
1773 }, | |
1774 keyCentric : function(keyX){ | |
1775 var arr = {}; | |
1776 for(var i = this.arr.length-1;i>=0;i--){ | |
1777 if(this.arr[i][keyX]){ | |
1778 if(!arr[this.arr[i][keyX].URI]){ arr[this.arr[i][keyX].URI] = []; } | |
1779 arr[this.arr[i][keyX].URI].push(this.arr[i]); | |
1780 } | |
1781 } | |
1782 return arr; | |
1783 }, | |
1784 get : function(key) | |
1785 { | |
1786 return (this.mappings[key]) ? this.mappings[key] : new jOWL.Ontology.Array(); | |
1787 }, | |
1788 getArray : function(){ | |
1789 //check mappings for presence, discard arr entries based on that, return remainder. | |
1790 for(var i = this.arr.length - 1;i>=0;i--){ | |
1791 var binding = this.arr[i], splice = false; | |
1792 for(key in binding){ | |
1793 if(!splice){ | |
1794 splice = (!this.mappings[key] || !this.mappings[key].contains(binding[key])); | |
1795 } | |
1796 } | |
1797 if(splice){ | |
1798 this.arr.splice(i, 1); | |
1799 } | |
1800 } | |
1801 return this; | |
1802 } | |
1803 }; | |
1804 | |
1805 /** | |
1806 Support for abstract SPARQl-DL syntax | |
1807 options.onComplete: function triggered when all individuals have been looped over | |
1808 options.childDepth: depth to fetch children, default 5, impacts performance | |
1809 options.chewsize: arrays will be processed in smaller chunks (asynchronous), with size indicated by chewsize, default 10 | |
1810 options.async: default true, query asynchronously | |
1811 parameters: prefill some sparql-dl parameters with jOWL objects | |
1812 execute: start query, results are passed through options.onComplete | |
1813 */ | |
1814 jOWL.SPARQL_DL = function(syntax, parameters, options){ | |
1815 if(!(this instanceof arguments.callee)){ return new jOWL.SPARQL_DL(syntax, parameters, options);} | |
1816 var self = this; | |
1817 this.parameters = $.extend({}, parameters); | |
1818 this.query = new jOWL.SPARQL_DL_Query(syntax, this.parameters).entries; | |
1819 this.result = new jOWL.SPARQL_DL_Result(); | |
1820 this.options = $.extend({onComplete: function(results){}}, options); | |
1821 }; | |
1822 | |
1823 jOWL.SPARQL_DL.prototype = { | |
1824 error: function(msg){ this.result.error = msg; return this.options.onComplete(this.result);}, | |
1825 /** | |
1826 if(options.async == false) then this method returns the result of options.onComplete, | |
1827 no matter what, result is always passed in options.onComplete | |
1828 */ | |
1829 execute : function(options){ | |
1830 var self = this; | |
1831 this.options = $.extend(this.options, options); | |
1832 if(this.query.error){ return this.error(this.query.error);} | |
1833 | |
1834 var resultobj = this.result; | |
1835 var i = 0; | |
1836 var loopoptions = $.extend({}, this.options); | |
1837 loopoptions.onComplete = function(results){ i++; resultobj = results; loop(i);}; | |
1838 | |
1839 if(!this.query.length){ | |
1840 resultobj.error = "no query found or query did not parse properly"; | |
1841 return self.options.onComplete(resultobj); | |
1842 } | |
1843 | |
1844 function loop(i){ | |
1845 if(i < self.query.length){ | |
1846 self.process(self.query[i], resultobj, loopoptions ); | |
1847 } | |
1848 else { | |
1849 for(var j =0;j<resultobj.results.length;j++){ //Convert Literals into strings | |
1850 var b = resultobj.results[j]; | |
1851 for(x in b){ | |
1852 if(b[x] instanceof jOWL.Literal){b[x] = b[x].name;} | |
1853 } | |
1854 } | |
1855 return self.options.onComplete(resultobj); | |
1856 } | |
1857 } | |
1858 loop(i); | |
1859 }, | |
1860 /** results are passed in the options.onComplete function */ | |
1861 process: function(entry, resultobj, options){ | |
1862 var self = this; | |
1863 options = $.extend({chewsize: 10, async : true, onComplete : function(results){}}, options); | |
1864 var q = entry[0]; | |
1865 var sizes = { | |
1866 "Type": [__.owl('Thing'), __.owl('Class')], | |
1867 "DirectType": [__.owl('Thing'), __.owl('Class')], | |
1868 "PropertyValue" : [false, false, false], | |
1869 "Class": [false], | |
1870 "Thing": [false], | |
1871 "ObjectProperty": [false], | |
1872 "DatatypeProperty": [false], | |
1873 "SubClassOf" : [__.owl('Class'), __.owl('Class')], | |
1874 "DirectSubClassOf" : [__.owl('Class'), __.owl('Class')] | |
1875 }; | |
1876 | |
1877 if(!sizes[q]){ return self.error("'"+q+"' queries are not implemented");} | |
1878 if(sizes[q].length != entry[1].length){ return self.error("invalid SPARQL-DL "+q+" specifications, "+sizes[q].length+" parameters required");} | |
1879 for(var i = 0;i<entry[1].length;i++){ | |
1880 var v = sizes[q][i]; | |
1881 if(v){ | |
1882 var m = entry[1][i]; | |
1883 if(typeof m != 'string' && m.type != v){ return self.error("Parameter "+i+" in SPARQL-DL Query for "+q+" must be of the type: "+v);} | |
1884 } | |
1885 } | |
1886 if(q == "DirectType"){ options.childDepth = 0; return self.fn.Type.call(self, entry[1], resultobj, options);} | |
1887 else if(q == "DirectSubClassOf"){ options.childDepth = 1; return self.fn.SubClassOf.call(self, entry[1], resultobj, options);} | |
1888 return self.fn[q].call(self, entry[1], resultobj, options); | |
1889 }, | |
1890 fn : { | |
1891 "SubClassOf" : function(syntax, resultobj, options){ | |
1892 var atom = new jOWL.SPARQL_DL.DoubleAtom(syntax, resultobj.head); | |
1893 var results = new SPARQL_DL_Array(); | |
1894 | |
1895 if(atom.source.isURI() && atom.target.isURI()){//assert | |
1896 if(resultobj.assert !== false){ | |
1897 var parents = atom.source.value.ancestors(); | |
1898 resultobj.assert = parents.contains(atom.target.value); | |
1899 } | |
1900 return options.onComplete(resultobj); | |
1901 } | |
1902 else if(atom.source.isURI()){//get parents | |
1903 atom.source.value.ancestors().each(function(){ | |
1904 results.push(atom.target.value, this); | |
1905 }); | |
1906 resultobj.filter(atom.target.value, results.get(atom.target.value)); | |
1907 resultobj.bind(results.getArray()); | |
1908 return options.onComplete(resultobj); | |
1909 } | |
1910 else if(atom.target.isURI()){//get children | |
1911 atom.target.value.descendants(options.childDepth).each(function(){ | |
1912 results.push(atom.source.value, this); | |
1913 }); | |
1914 resultobj.filter(atom.source.value, results.get(atom.source.value)); | |
1915 resultobj.bind(results.getArray()); | |
1916 return options.onComplete(resultobj); | |
1917 } | |
1918 else{//both undefined | |
1919 return this.error('Unsupported SubClassOf query'); | |
1920 } | |
1921 }, | |
1922 "Type" : function(syntax, resultobj, options){ | |
1923 var atom = new jOWL.SPARQL_DL.DoubleAtom(syntax, resultobj.head); | |
1924 | |
1925 function addIndividual(cl){ | |
1926 if(indivs[this.URI]){ return;} | |
1927 var b = results.push(atom.source.value, this); | |
1928 if(addTarget){ b.bind(atom.target.value, cl);} | |
1929 indivs[this.URI] = true; | |
1930 } | |
1931 | |
1932 function traverse(node, match){ | |
1933 var a = node.parents(); | |
1934 var found = false; | |
1935 if(a.contains(match)){ found = true;} | |
1936 else { | |
1937 a.each(function(){ | |
1938 if(this == jOWL.Thing){ return;} | |
1939 if(!found && traverse(this, match)){ found = true;} }); | |
1940 } | |
1941 return found; | |
1942 } | |
1943 | |
1944 if(atom.source.isURI() && atom.target.isURI()){//assert | |
1945 return jOWL.SPARQL_DL.priv.assert(resultobj, function(){ | |
1946 var cl = atom.source.value.owlClass(); | |
1947 if(cl.URI == atom.target.value.URI){ return true;} | |
1948 return traverse(cl, atom.target.value); | |
1949 }, options.onComplete); | |
1950 } | |
1951 else if(atom.source.getURIs() && !atom.target.getURIs()){//get class | |
1952 var results = new SPARQL_DL_Array(); | |
1953 var addSource = !atom.source.isURI(); | |
1954 var addTarget = !atom.target.isURI(); | |
1955 atom.source.getURIs().each(function(){ | |
1956 var b; | |
1957 if(addTarget){ b = results.push(atom.target.value, this.owlClass());} | |
1958 if(addSource){ | |
1959 if(addTarget){ b.bind(atom.source.value, this);} | |
1960 else {results.push(atom.source.value, this);} | |
1961 } | |
1962 }); | |
1963 if(addSource){ resultobj.filter(atom.source.value, results.get(atom.source.value));} | |
1964 if(addTarget){ resultobj.filter(atom.target.value, results.get(atom.target.value));} | |
1965 resultobj.bind(results.getArray()); | |
1966 return options.onComplete(resultobj); | |
1967 } | |
1968 else if(atom.target.getURIs()){//get Individuals, slow | |
1969 var addTarget = !atom.target.isURI(); | |
1970 var classlist = atom.target.getURIs(), | |
1971 classes = {}, indivs = {}; | |
1972 | |
1973 var results = new SPARQL_DL_Array(); | |
1974 | |
1975 | |
1976 classlist.each(function(){ //expand list of classes, not very fast! | |
1977 if(classes[this.URI]){ return;} | |
1978 var oneOf = this.oneOf(), cl = this; | |
1979 if(oneOf.length){ oneOf.each(function(){ addIndividual.call(this, cl);});} | |
1980 else{ this.descendants(options.childDepth).each(function(){ //this is the slower call | |
1981 classes[this.URI] = true; | |
1982 }); } | |
1983 classes[this.URI] = true; | |
1984 }); | |
1985 | |
1986 for(x in classes){ | |
1987 var individuals = jOWL.index("Thing")[x]; | |
1988 if(individuals){ | |
1989 var cl = jOWL.index('ID')[x]; | |
1990 if(options.onUpdate){ options.onUpdate(individuals);} | |
1991 individuals.each(function(){ | |
1992 addIndividual.call(this, cl); | |
1993 }); | |
1994 } | |
1995 } | |
1996 resultobj.filter(atom.source.value, results.get(atom.source.value)); | |
1997 resultobj.bind(results.getArray()); | |
1998 return options.onComplete(resultobj); | |
1999 } | |
2000 return this.error('Unsupported Type query'); | |
2001 }, | |
2002 "Thing" : function(syntax, resultobj, options){ | |
2003 jOWL.SPARQL_DL.priv.IDQuery(syntax[0], "isThing", resultobj, options); | |
2004 }, | |
2005 "Class" : function(syntax, resultobj, options){ console.log('cl'); | |
2006 jOWL.SPARQL_DL.priv.IDQuery(syntax[0], "isClass", resultobj, options); | |
2007 }, | |
2008 "ObjectProperty" : function(syntax, resultobj, options){ | |
2009 jOWL.SPARQL_DL.priv.PropertyQuery(syntax[0], jOWL.index("property").items, "isObjectProperty", resultobj, options); | |
2010 }, | |
2011 "DatatypeProperty" : function(syntax, resultobj, options){ | |
2012 jOWL.SPARQL_DL.priv.PropertyQuery(syntax[0], jOWL.index("property").items, "isDatatypeProperty", resultobj, options); | |
2013 }, | |
2014 "PropertyValue" : function(syntax, resultobj, options){ | |
2015 var atom = new jOWL.SPARQL_DL.TripleAtom(syntax, resultobj.head); | |
2016 | |
2017 if(atom.source.isURI() && atom.property.isURI() && atom.target.isURI()){//assert | |
2018 if(resultobj.assert !== false){ | |
2019 jOWL.SPARQL_DL.priv.PropertyValuegetSourceInfo(atom.source.value, atom.property.value, atom.target.value, resultobj, { assert : true }); | |
2020 } | |
2021 return options.onComplete(resultobj); | |
2022 } | |
2023 | |
2024 if(!atom.source.getURIs()){ | |
2025 jOWL.SPARQL_DL.priv.IDQuery(atom.source.value, ["isClass", "isThing"], resultobj, options); | |
2026 return; | |
2027 } | |
2028 var filterTarget = atom.target.isVar() ? atom.target.value : false; | |
2029 var filterProperty = atom.property.isVar() ? atom.property.value : false; | |
2030 var filterSource = atom.source.isVar() ? atom.source.value : false; | |
2031 jOWL.SPARQL_DL.priv.PropertyValuegetSourceInfo(atom.source.getURIs(), atom.property.getURIs(), atom.target.getURIs(), resultobj, | |
2032 { | |
2033 filterTarget : filterTarget, filterProperty : filterProperty, filterSource : filterSource | |
2034 }); | |
2035 return options.onComplete(resultobj); | |
2036 } | |
2037 } | |
2038 }; | |
2039 | |
2040 jOWL.SPARQL_DL.priv = { | |
2041 assert : function(resultobj, fn, onComplete){ | |
2042 if(resultobj.assert !== false){ | |
2043 resultobj.assert = fn(); | |
2044 } | |
2045 onComplete(resultobj); | |
2046 }, | |
2047 //reusable function | |
2048 PropertyValuegetSourceInfo : function(jSource, property, target, resultobj, options){ | |
2049 if(!(jSource.isArray)){ | |
2050 return jOWL.SPARQL_DL.priv.PropertyValuegetSourceInfo(new jOWL.Ontology.Array([jSource]), property, target, resultobj, options); | |
2051 } | |
2052 | |
2053 options = $.extend({}, options); | |
2054 var results = new SPARQL_DL_Array([options.filterSource, options.filterProperty, options.filterTarget]), | |
2055 match = false; | |
2056 jSource.each(function(){ | |
2057 var source = this; | |
2058 if(target && target.isArray && target.length == 1){ | |
2059 var literal = target.get(0).test; | |
2060 if(literal){ target = literal;}//unwrap literal expressions | |
2061 } | |
2062 var restrictions = source.sourceof(property, target); | |
2063 if(options.assert){ | |
2064 if(restrictions.length > 0){ match = true;} | |
2065 return; | |
2066 } | |
2067 if(!restrictions.length){ return;} | |
2068 restrictions.each(function(){ | |
2069 var binding = new _Binding(results); | |
2070 if(options.filterSource){ | |
2071 binding.bind(options.filterSource, source); | |
2072 if(!options.filterProperty && !options.filterTarget){ results.add(binding); return false;} | |
2073 } | |
2074 if(options.filterProperty){ | |
2075 binding.bind(options.filterProperty, this.property); | |
2076 } | |
2077 if(options.filterTarget){ | |
2078 binding.bind(options.filterTarget, this.getTarget()); | |
2079 } | |
2080 results.add(binding); | |
2081 }); | |
2082 return true; | |
2083 }); | |
2084 if(options.assert){ | |
2085 resultobj.assert = match; | |
2086 return resultobj.assert; | |
2087 } | |
2088 if(options.filterSource){ resultobj.filter(options.filterSource, results.get(options.filterSource));} | |
2089 if(options.filterProperty){ resultobj.filter(options.filterProperty, results.get(options.filterProperty));} | |
2090 if(options.filterTarget) { resultobj.filter(options.filterTarget, results.get(options.filterTarget));} | |
2091 resultobj.bind(results.getArray()); | |
2092 }, | |
2093 hasClassID: function(match, classID){ | |
2094 if(Object.prototype.toString.call(classID) === '[object Array]'){ | |
2095 for(var i =0;i<classID.length;i++){ | |
2096 if(match[classID]){ return true;} | |
2097 } | |
2098 } else if(match[classID]){ return true;} | |
2099 return false; | |
2100 }, | |
2101 IDQuery : function(parameter, classID, resultobj, options){ | |
2102 var atom = new jOWL.SPARQL_DL.Atom(parameter, resultobj.head); | |
2103 if(atom.isURI()){ | |
2104 return jOWL.SPARQL_DL.priv.assert(resultobj, function(){ | |
2105 return jOWL.SPARQL_DL.priv.hasClassID(atom.getURIs().get(0), classID); | |
2106 }, options.onComplete); | |
2107 } | |
2108 var results = new SPARQL_DL_Array(); | |
2109 for(x in jOWL.index("ID")){ | |
2110 var match = jOWL.index("ID")[x]; | |
2111 if(jOWL.SPARQL_DL.priv.hasClassID(match, classID)){ results.push(parameter, match);} | |
2112 } | |
2113 resultobj.filter(parameter, results.get(parameter)); | |
2114 resultobj.bind(results.getArray()); | |
2115 options.onComplete(resultobj); | |
2116 }, | |
2117 PropertyQuery : function(parameter, index, className, resultobj, options){ | |
2118 var atom = new jOWL.SPARQL_DL.Atom(parameter, resultobj.head); | |
2119 if(atom.isURI()){ | |
2120 return jOWL.SPARQL_DL.priv.assert(resultobj, function(){ | |
2121 return jOWL.SPARQL_DL.priv.hasClassID(atom.getURIs().get(0), className); | |
2122 }, options.onComplete); | |
2123 } | |
2124 var results = new SPARQL_DL_Array(); | |
2125 var tr = new jOWL.throttle(index, $.extend({}, options, { | |
2126 modify : function(result){ | |
2127 if(!result.jOWL){ result = jOWL(result);} | |
2128 if(jOWL.SPARQL_DL.priv.hasClassID(result, className)){results.push(parameter, result);} | |
2129 return false; | |
2130 }, | |
2131 onComplete : function(){ | |
2132 resultobj.filter(parameter, results.get(parameter)); | |
2133 resultobj.bind(results.getArray()); | |
2134 options.onComplete(resultobj); | |
2135 } | |
2136 })); | |
2137 } | |
2138 }; | |
2139 | |
2140 jOWL.SPARQL_DL.TripleAtom = function(syntax, store){ | |
2141 this.source = new jOWL.SPARQL_DL.Atom(syntax[0], store); | |
2142 this.property = new jOWL.SPARQL_DL.Atom(syntax[1], store); | |
2143 this.target = new jOWL.SPARQL_DL.Atom(syntax[2], store); | |
2144 }; | |
2145 | |
2146 jOWL.SPARQL_DL.DoubleAtom = function(syntax, store){ | |
2147 this.source = new jOWL.SPARQL_DL.Atom(syntax[0], store); | |
2148 this.target = new jOWL.SPARQL_DL.Atom(syntax[1], store); | |
2149 }; | |
2150 | |
2151 | |
2152 jOWL.SPARQL_DL.Atom = function(syntax, store){ | |
2153 this.value = syntax; | |
2154 this.type = 0; | |
2155 if(typeof syntax == 'string'){ | |
2156 if(syntax.indexOf('?') === 0){ | |
2157 this.type = this.VAR; | |
2158 if(store && store[syntax]){ this.mappings = store[syntax];} | |
2159 } else { | |
2160 this.type = this.LITERAL; | |
2161 } | |
2162 } else { | |
2163 this.type = this.URI; | |
2164 } | |
2165 }; | |
2166 | |
2167 jOWL.SPARQL_DL.Atom.prototype = { | |
2168 URI : 1, LITERAL : 2, VAR : 3, | |
2169 getURIs : function(){ | |
2170 if(this.isURI()){return new jOWL.Ontology.Array([this.value]);} | |
2171 return this.mappings; | |
2172 }, | |
2173 isVar : function(){return this.type == this.VAR;}, | |
2174 isLiteral : function(){return this.type == this.LITERAL;}, | |
2175 isURI : function(){ return this.type == this.URI;} | |
2176 }; | |
2177 | |
2178 /** | |
2179 * @return Associative array of parameters in the current documents URL | |
2180 */ | |
2181 jOWL.getURLParameters = function(){ | |
2182 var href = window.location.href.split("?", 2), param = {}; | |
2183 if(href.length == 1){ return {};} | |
2184 var qstr = href[1].split('&'); | |
2185 for(var i =0;i<qstr.length;i++){ | |
2186 var arr = qstr[i].split("="); | |
2187 if(arr.length == 2){ param[arr[0]] = arr[1];} | |
2188 } | |
2189 return param; | |
2190 }; | |
2191 | |
2192 /** | |
2193 Without arguments this function will parse the current url and see if any parameters are defined, returns a JOWL object | |
2194 @return With argument it will return a string that identifies the potential permalink fr the given entry | |
2195 */ | |
2196 jOWL.permalink = function(entry){ | |
2197 if(!entry){ | |
2198 var param = jOWL.getURLParameters(); | |
2199 if(param.owlClass){ return jOWL(unescape(param.owlClass));} | |
2200 } | |
2201 else { | |
2202 if(!entry.URI){ return false;} | |
2203 var href = window.location.href.split("?", 2); | |
2204 if(window.location.search){ href = href[0];} | |
2205 if(entry.isClass){ return href+'?owlClass='+escape(entry.URI);} | |
2206 } | |
2207 return false; | |
2208 }; | |
2209 | |
2210 /** Convert an item into Manchester syntax, currently only for oneOf | |
2211 * @return String | |
2212 */ | |
2213 jOWL.Manchester = function(owlElement){ | |
2214 var syntax = []; | |
2215 if(owlElement.isClass){ | |
2216 var oneOf = owlElement.oneOf().map(function(){ return this.label();}); | |
2217 if(oneOf.length){ syntax.push("{ "+oneOf.join(", ")+" }");} | |
2218 } | |
2219 return syntax.join(", "); | |
2220 }; | |
2221 | |
2222 })(jQuery); | |
2223 | |
2224 /** | |
2225 * @return 1 for exact match, 0 for partial match, -1 for no match. | |
2226 */ | |
2227 String.prototype.searchMatch = function(matchstring, exact){ | |
2228 if(this.search(new RegExp(matchstring, "i")) > -1){ return 1;} //contained within | |
2229 var c = 0; var arr = matchstring.match(new RegExp("\\w+", "ig")); | |
2230 for(var i = 0;i<arr.length;i++){ if(this.search(arr[i]) > -1){ c++;} } | |
2231 if(c == arr.length){ return 0;} //word shift | |
2232 return -1; //nomatch | |
2233 }; | |
2234 /** | |
2235 * @return Modified String. | |
2236 */ | |
2237 String.prototype.beautify = function(){ | |
2238 var e1 = new RegExp("([a-z0-9])([A-Z])", "g"); | |
2239 var e2 = new RegExp("([A-Z])([A-Z0-9])([a-z])", "g"); | |
2240 var e3 = new RegExp("_", "g"); | |
2241 return this.replace(e1, "$1 $2").replace(e2, "$1 $2$3").replace(e3, " "); | |
2242 }; |