Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/rdflib/extras/infixowl.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4f3585e2f14b |
---|---|
1 #!/usr/bin/env python | |
2 # -*- coding: utf-8 -*- | |
3 from __future__ import absolute_import | |
4 from __future__ import division | |
5 from __future__ import print_function | |
6 | |
7 from six import PY3 | |
8 | |
9 | |
10 __doc__ = """ | |
11 RDFLib Python binding for OWL Abstract Syntax | |
12 | |
13 see: http://www.w3.org/TR/owl-semantics/syntax.html | |
14 http://owl-workshop.man.ac.uk/acceptedLong/submission_9.pdf | |
15 | |
16 3.2.3 Axioms for complete classes without using owl:equivalentClass | |
17 | |
18 Named class description of type 2 (with owl:oneOf) or type 4-6 | |
19 (with owl:intersectionOf, owl:unionOf or owl:complementOf | |
20 | |
21 | |
22 Uses Manchester Syntax for __repr__ | |
23 | |
24 >>> exNs = Namespace('http://example.com/') | |
25 >>> namespace_manager = NamespaceManager(Graph()) | |
26 >>> namespace_manager.bind('ex', exNs, override=False) | |
27 >>> namespace_manager.bind('owl', OWL_NS, override=False) | |
28 >>> g = Graph() | |
29 >>> g.namespace_manager = namespace_manager | |
30 | |
31 Now we have an empty graph, we can construct OWL classes in it | |
32 using the Python classes defined in this module | |
33 | |
34 >>> a = Class(exNs.Opera, graph=g) | |
35 | |
36 Now we can assert rdfs:subClassOf and owl:equivalentClass relationships | |
37 (in the underlying graph) with other classes using the 'subClassOf' | |
38 and 'equivalentClass' descriptors which can be set to a list | |
39 of objects for the corresponding predicates. | |
40 | |
41 >>> a.subClassOf = [exNs.MusicalWork] | |
42 | |
43 We can then access the rdfs:subClassOf relationships | |
44 | |
45 >>> print(list(a.subClassOf)) | |
46 [Class: ex:MusicalWork ] | |
47 | |
48 This can also be used against already populated graphs: | |
49 | |
50 >>> owlGraph = Graph().parse(OWL_NS) #doctest: +SKIP | |
51 >>> namespace_manager.bind('owl', OWL_NS, override=False) #doctest: +SKIP | |
52 >>> owlGraph.namespace_manager = namespace_manager #doctest: +SKIP | |
53 >>> list(Class(OWL_NS.Class, graph=owlGraph).subClassOf) #doctest: +SKIP | |
54 [Class: rdfs:Class ] | |
55 | |
56 Operators are also available. For instance we can add ex:Opera to the extension | |
57 of the ex:CreativeWork class via the '+=' operator | |
58 | |
59 >>> a #doctest: +SKIP | |
60 Class: ex:Opera SubClassOf: ex:MusicalWork | |
61 >>> b = Class(exNs.CreativeWork, graph=g) | |
62 >>> b += a | |
63 >>> print(sorted(a.subClassOf, key=lambda c:c.identifier)) #doctest: +SKIP | |
64 [Class: ex:CreativeWork , Class: ex:MusicalWork ] | |
65 | |
66 And we can then remove it from the extension as well | |
67 | |
68 >>> b -= a | |
69 >>> a #doctest: +SKIP | |
70 Class: ex:Opera SubClassOf: ex:MusicalWork | |
71 | |
72 Boolean class constructions can also be created with Python operators. | |
73 For example, The | operator can be used to construct a class consisting of a | |
74 owl:unionOf the operands: | |
75 | |
76 >>> c = a | b | Class(exNs.Work, graph=g) | |
77 >>> c #doctest: +SKIP | |
78 ( ex:Opera OR ex:CreativeWork OR ex:Work ) | |
79 | |
80 Boolean class expressions can also be operated as lists (using python list | |
81 operators) | |
82 | |
83 >>> del c[c.index(Class(exNs.Work, graph=g))] | |
84 >>> c #doctest: +SKIP | |
85 ( ex:Opera OR ex:CreativeWork ) | |
86 | |
87 The '&' operator can be used to construct class intersection: | |
88 | |
89 >>> woman = Class(exNs.Female, graph=g) & Class(exNs.Human, graph=g) | |
90 >>> woman.identifier = exNs.Woman | |
91 >>> woman #doctest: +SKIP | |
92 ( ex:Female AND ex:Human ) | |
93 >>> len(woman) | |
94 2 | |
95 | |
96 Enumerated classes can also be manipulated | |
97 | |
98 >>> contList = [Class(exNs.Africa, graph=g), Class(exNs.NorthAmerica, graph=g)] | |
99 >>> EnumeratedClass(members=contList, graph=g) #doctest: +SKIP | |
100 { ex:Africa ex:NorthAmerica } | |
101 | |
102 owl:Restrictions can also be instantiated: | |
103 | |
104 >>> Restriction(exNs.hasParent, graph=g, allValuesFrom=exNs.Human) #doctest: +SKIP | |
105 ( ex:hasParent ONLY ex:Human ) | |
106 | |
107 Restrictions can also be created using Manchester OWL syntax in 'colloquial' | |
108 Python | |
109 >>> exNs.hasParent | some | Class(exNs.Physician, graph=g) #doctest: +SKIP | |
110 ( ex:hasParent SOME ex:Physician ) | |
111 | |
112 >>> Property(exNs.hasParent,graph=g) | max | Literal(1) #doctest: +SKIP | |
113 ( ex:hasParent MAX 1 ) | |
114 | |
115 >>> print(g.serialize(format='pretty-xml')) #doctest: +SKIP | |
116 | |
117 """ | |
118 | |
119 import itertools | |
120 | |
121 from rdflib import ( | |
122 BNode, | |
123 Literal, | |
124 Namespace, | |
125 RDF, | |
126 RDFS, | |
127 URIRef, | |
128 Variable | |
129 ) | |
130 from rdflib.graph import Graph | |
131 from rdflib.collection import Collection | |
132 from rdflib.namespace import XSD as _XSD_NS | |
133 from rdflib.namespace import NamespaceManager | |
134 from rdflib.term import Identifier | |
135 from rdflib.util import first | |
136 | |
137 import logging | |
138 logger = logging.getLogger(__name__) | |
139 | |
140 | |
141 """ | |
142 From: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/384122 | |
143 | |
144 Python has the wonderful "in" operator and it would be nice to have additional | |
145 infix operator like this. This recipe shows how (almost) arbitrary infix | |
146 operators can be defined. | |
147 | |
148 """ | |
149 | |
150 __all__ = [ | |
151 'OWL_NS', | |
152 'nsBinds', | |
153 'ACE_NS', | |
154 'CLASS_RELATIONS', | |
155 'some', | |
156 'only', | |
157 'max', | |
158 'min', | |
159 'exactly', | |
160 'value', | |
161 'PropertyAbstractSyntax', | |
162 'AllClasses', | |
163 'AllDifferent', | |
164 'AllProperties', | |
165 'AnnotatableTerms', | |
166 'BooleanClass', | |
167 'Callable', | |
168 'CastClass', | |
169 'Class', | |
170 'ClassNamespaceFactory', | |
171 'classOrIdentifier', | |
172 'classOrTerm', | |
173 'CommonNSBindings', | |
174 'ComponentTerms', | |
175 'DeepClassClear', | |
176 'EnumeratedClass', | |
177 'generateQName', | |
178 'GetIdentifiedClasses', | |
179 'Individual', | |
180 'MalformedClass', | |
181 'manchesterSyntax', | |
182 'Ontology', | |
183 'OWLRDFListProxy', | |
184 'Property', | |
185 'propertyOrIdentifier', | |
186 'Restriction', | |
187 'termDeletionDecorator', | |
188 ] | |
189 | |
190 # definition of an Infix operator class | |
191 # this recipe also works in jython | |
192 # calling sequence for the infix is either: | |
193 # x |op| y | |
194 # or: | |
195 # x <<op>> y | |
196 | |
197 | |
198 class Infix: | |
199 def __init__(self, function): | |
200 self.function = function | |
201 | |
202 def __ror__(self, other): | |
203 return Infix(lambda x, self=self, other=other: self.function(other, x)) | |
204 | |
205 def __or__(self, other): | |
206 return self.function(other) | |
207 | |
208 def __rlshift__(self, other): | |
209 return Infix(lambda x, self=self, other=other: self.function(other, x)) | |
210 | |
211 def __rshift__(self, other): | |
212 return self.function(other) | |
213 | |
214 def __call__(self, value1, value2): | |
215 return self.function(value1, value2) | |
216 | |
217 | |
218 OWL_NS = Namespace("http://www.w3.org/2002/07/owl#") | |
219 | |
220 nsBinds = { | |
221 'skos': 'http://www.w3.org/2004/02/skos/core#', | |
222 'rdf': RDF, | |
223 'rdfs': RDFS, | |
224 'owl': OWL_NS, | |
225 'list': URIRef('http://www.w3.org/2000/10/swap/list#'), | |
226 'dc': "http://purl.org/dc/elements/1.1/", | |
227 } | |
228 | |
229 | |
230 def generateQName(graph, uri): | |
231 prefix, uri, localName = graph.compute_qname(classOrIdentifier(uri)) | |
232 return u':'.join([prefix, localName]) | |
233 | |
234 | |
235 def classOrTerm(thing): | |
236 if isinstance(thing, Class): | |
237 return thing.identifier | |
238 else: | |
239 assert isinstance(thing, (URIRef, BNode, Literal)) | |
240 return thing | |
241 | |
242 | |
243 def classOrIdentifier(thing): | |
244 if isinstance(thing, (Property, Class)): | |
245 return thing.identifier | |
246 else: | |
247 assert isinstance(thing, (URIRef, BNode)), \ | |
248 "Expecting a Class, Property, URIRef, or BNode.. not a %s" % thing | |
249 return thing | |
250 | |
251 | |
252 def propertyOrIdentifier(thing): | |
253 if isinstance(thing, Property): | |
254 return thing.identifier | |
255 else: | |
256 assert isinstance(thing, URIRef) | |
257 return thing | |
258 | |
259 | |
260 def manchesterSyntax(thing, store, boolean=None, transientList=False): | |
261 """ | |
262 Core serialization | |
263 """ | |
264 assert thing is not None | |
265 if boolean: | |
266 if transientList: | |
267 liveChildren = iter(thing) | |
268 children = [manchesterSyntax(child, store) for child in thing] | |
269 else: | |
270 liveChildren = iter(Collection(store, thing)) | |
271 children = [manchesterSyntax( | |
272 child, store) for child in Collection(store, thing)] | |
273 if boolean == OWL_NS.intersectionOf: | |
274 childList = [] | |
275 named = [] | |
276 for child in liveChildren: | |
277 if isinstance(child, URIRef): | |
278 named.append(child) | |
279 else: | |
280 childList.append(child) | |
281 if named: | |
282 def castToQName(x): | |
283 prefix, uri, localName = store.compute_qname(x) | |
284 return ':'.join([prefix, localName]) | |
285 | |
286 if len(named) > 1: | |
287 prefix = u'( ' + u' AND '.join(map( | |
288 castToQName, named)) + u' )' | |
289 else: | |
290 prefix = manchesterSyntax(named[0], store) | |
291 if childList: | |
292 return str(prefix) + u' THAT ' + u' AND '.join( | |
293 [str(manchesterSyntax(x, store)) for x in childList]) | |
294 else: | |
295 return prefix | |
296 else: | |
297 return u'( ' + u' AND '.join( | |
298 [str(c) for c in children]) + u' )' | |
299 elif boolean == OWL_NS.unionOf: | |
300 return u'( ' + u' OR '.join([str(c) for c in children]) + ' )' | |
301 elif boolean == OWL_NS.oneOf: | |
302 return u'{ ' + u' '.join([str(c) for c in children]) + ' }' | |
303 else: | |
304 assert boolean == OWL_NS.complementOf | |
305 elif OWL_NS.Restriction in store.objects( | |
306 subject=thing, predicate=RDF.type): | |
307 prop = list( | |
308 store.objects(subject=thing, predicate=OWL_NS.onProperty))[0] | |
309 prefix, uri, localName = store.compute_qname(prop) | |
310 propString = u':'.join([prefix, localName]) | |
311 label = first(store.objects(subject=prop, predicate=RDFS.label)) | |
312 if label: | |
313 propString = "'%s'" % label | |
314 for onlyClass in store.objects( | |
315 subject=thing, predicate=OWL_NS.allValuesFrom): | |
316 return u'( %s ONLY %s )' % ( | |
317 propString, manchesterSyntax(onlyClass, store)) | |
318 for val in store.objects(subject=thing, predicate=OWL_NS.hasValue): | |
319 return u'( %s VALUE %s )' % ( | |
320 propString, | |
321 manchesterSyntax(val, store)) | |
322 for someClass in store.objects( | |
323 subject=thing, predicate=OWL_NS.someValuesFrom): | |
324 return u'( %s SOME %s )' % ( | |
325 propString, manchesterSyntax(someClass, store)) | |
326 cardLookup = {OWL_NS.maxCardinality: 'MAX', | |
327 OWL_NS.minCardinality: 'MIN', | |
328 OWL_NS.cardinality: 'EQUALS'} | |
329 for s, p, o in store.triples_choices( | |
330 (thing, list(cardLookup.keys()), None)): | |
331 return u'( %s %s %s )' % ( | |
332 propString, cardLookup[p], o) | |
333 compl = list(store.objects(subject=thing, predicate=OWL_NS.complementOf)) | |
334 if compl: | |
335 return '( NOT %s )' % (manchesterSyntax(compl[0], store)) | |
336 else: | |
337 prolog = '\n'.join( | |
338 ["PREFIX %s: <%s>" % (k, nsBinds[k]) for k in nsBinds]) | |
339 qstr = \ | |
340 prolog + \ | |
341 "\nSELECT ?p ?bool WHERE {?class a owl:Class; ?p ?bool ." + \ | |
342 "?bool rdf:first ?foo }" | |
343 initb = {Variable("?class"): thing} | |
344 for boolProp, col in \ | |
345 store.query(qstr, processor="sparql", initBindings=initb): | |
346 if not isinstance(thing, URIRef): | |
347 return manchesterSyntax(col, store, boolean=boolProp) | |
348 try: | |
349 prefix, uri, localName = store.compute_qname(thing) | |
350 qname = u':'.join([prefix, localName]) | |
351 except Exception: | |
352 if isinstance(thing, BNode): | |
353 return thing.n3() | |
354 return u"<" + thing + ">" | |
355 logger.debug(list(store.objects(subject=thing, predicate=RDF.type))) | |
356 raise | |
357 return '[]' # +thing._id.encode('utf-8')+'</em>' | |
358 label = first(Class(thing, graph=store).label) | |
359 if label: | |
360 return label | |
361 else: | |
362 return qname | |
363 | |
364 | |
365 def GetIdentifiedClasses(graph): | |
366 for c in graph.subjects(predicate=RDF.type, object=OWL_NS.Class): | |
367 if isinstance(c, URIRef): | |
368 yield Class(c) | |
369 | |
370 | |
371 def termDeletionDecorator(prop): | |
372 def someFunc(func): | |
373 func.property = prop | |
374 return func | |
375 return someFunc | |
376 | |
377 | |
378 class TermDeletionHelper: | |
379 def __init__(self, prop): | |
380 self.prop = prop | |
381 | |
382 def __call__(self, f): | |
383 def _remover(inst): | |
384 inst.graph.remove((inst.identifier, self.prop, None)) | |
385 return _remover | |
386 | |
387 | |
388 class Individual(object): | |
389 """ | |
390 A typed individual | |
391 """ | |
392 factoryGraph = Graph() | |
393 | |
394 def serialize(self, graph): | |
395 for fact in self.factoryGraph.triples((self.identifier, None, None)): | |
396 graph.add(fact) | |
397 | |
398 def __init__(self, identifier=None, graph=None): | |
399 self.__identifier = identifier is not None and identifier or BNode() | |
400 if graph is None: | |
401 self.graph = self.factoryGraph | |
402 else: | |
403 self.graph = graph | |
404 self.qname = None | |
405 if not isinstance(self.identifier, BNode): | |
406 try: | |
407 prefix, uri, localName = self.graph.compute_qname( | |
408 self.identifier) | |
409 self.qname = u':'.join([prefix, localName]) | |
410 except: | |
411 pass | |
412 | |
413 def clearInDegree(self): | |
414 self.graph.remove((None, None, self.identifier)) | |
415 | |
416 def clearOutDegree(self): | |
417 self.graph.remove((self.identifier, None, None)) | |
418 | |
419 def delete(self): | |
420 self.clearInDegree() | |
421 self.clearOutDegree() | |
422 | |
423 def replace(self, other): | |
424 for s, p, o in self.graph.triples((None, None, self.identifier)): | |
425 self.graph.add((s, p, classOrIdentifier(other))) | |
426 self.delete() | |
427 | |
428 def _get_type(self): | |
429 for _t in self.graph.objects( | |
430 subject=self.identifier, predicate=RDF.type): | |
431 yield _t | |
432 | |
433 def _set_type(self, kind): | |
434 if not kind: | |
435 return | |
436 if isinstance(kind, (Individual, Identifier)): | |
437 self.graph.add( | |
438 (self.identifier, RDF.type, classOrIdentifier(kind))) | |
439 else: | |
440 for c in kind: | |
441 assert isinstance(c, (Individual, Identifier)) | |
442 self.graph.add( | |
443 (self.identifier, RDF.type, classOrIdentifier(c))) | |
444 | |
445 @TermDeletionHelper(RDF.type) | |
446 def _delete_type(self): | |
447 """ | |
448 >>> g = Graph() | |
449 >>> b=Individual(OWL_NS.Restriction,g) | |
450 >>> b.type = RDF.Resource | |
451 >>> len(list(b.type)) | |
452 1 | |
453 >>> del b.type | |
454 >>> len(list(b.type)) | |
455 0 | |
456 """ | |
457 pass | |
458 | |
459 type = property(_get_type, _set_type, _delete_type) | |
460 | |
461 def _get_identifier(self): | |
462 return self.__identifier | |
463 | |
464 def _set_identifier(self, i): | |
465 assert i | |
466 if i != self.__identifier: | |
467 oldStmtsOut = [(p, o) for s, p, o in self.graph.triples( | |
468 (self.__identifier, None, None))] | |
469 oldStmtsIn = [(s, p) for s, p, o in self.graph.triples( | |
470 (None, None, self.__identifier))] | |
471 for p1, o1 in oldStmtsOut: | |
472 self.graph.remove((self.__identifier, p1, o1)) | |
473 for s1, p1 in oldStmtsIn: | |
474 self.graph.remove((s1, p1, self.__identifier)) | |
475 self.__identifier = i | |
476 self.graph.addN( | |
477 [(i, p1, o1, self.graph) for p1, o1 in oldStmtsOut]) | |
478 self.graph.addN([(s1, p1, i, self.graph) for s1, p1 in oldStmtsIn]) | |
479 if not isinstance(i, BNode): | |
480 try: | |
481 prefix, uri, localName = self.graph.compute_qname(i) | |
482 self.qname = u':'.join([prefix, localName]) | |
483 except: | |
484 pass | |
485 | |
486 identifier = property(_get_identifier, _set_identifier) | |
487 | |
488 def _get_sameAs(self): | |
489 for _t in self.graph.objects( | |
490 subject=self.identifier, predicate=OWL_NS.sameAs): | |
491 yield _t | |
492 | |
493 def _set_sameAs(self, term): | |
494 # if not kind: | |
495 # return | |
496 if isinstance(term, (Individual, Identifier)): | |
497 self.graph.add( | |
498 (self.identifier, OWL_NS.sameAs, classOrIdentifier(term))) | |
499 else: | |
500 for c in term: | |
501 assert isinstance(c, (Individual, Identifier)) | |
502 self.graph.add( | |
503 (self.identifier, OWL_NS.sameAs, classOrIdentifier(c))) | |
504 | |
505 @TermDeletionHelper(OWL_NS.sameAs) | |
506 def _delete_sameAs(self): | |
507 pass | |
508 | |
509 sameAs = property(_get_sameAs, _set_sameAs, _delete_sameAs) | |
510 | |
511 | |
512 ACE_NS = Namespace('http://attempto.ifi.uzh.ch/ace_lexicon#') | |
513 | |
514 | |
515 class AnnotatableTerms(Individual): | |
516 """ | |
517 Terms in an OWL ontology with rdfs:label and rdfs:comment | |
518 """ | |
519 | |
520 def __init__(self, | |
521 identifier, | |
522 graph=None, | |
523 nameAnnotation=None, | |
524 nameIsLabel=False): | |
525 super(AnnotatableTerms, self).__init__(identifier, graph) | |
526 if nameAnnotation: | |
527 self.setupACEAnnotations() | |
528 self.PN_sgProp.extent = [(self.identifier, | |
529 self.handleAnnotation(nameAnnotation))] | |
530 if nameIsLabel: | |
531 self.label = [nameAnnotation] | |
532 | |
533 def handleAnnotation(self, val): | |
534 return val if isinstance(val, Literal) else Literal(val) | |
535 | |
536 def setupACEAnnotations(self): | |
537 self.graph.bind('ace', ACE_NS, override=False) | |
538 | |
539 # PN_sg singular form of a proper name () | |
540 self.PN_sgProp = Property(ACE_NS.PN_sg, | |
541 baseType=OWL_NS.AnnotationProperty, | |
542 graph=self.graph) | |
543 | |
544 # CN_sg singular form of a common noun | |
545 self.CN_sgProp = Property(ACE_NS.CN_sg, | |
546 baseType=OWL_NS.AnnotationProperty, | |
547 graph=self.graph) | |
548 | |
549 # CN_pl plural form of a common noun | |
550 self.CN_plProp = Property(ACE_NS.CN_pl, | |
551 baseType=OWL_NS.AnnotationProperty, | |
552 graph=self.graph) | |
553 | |
554 # singular form of a transitive verb | |
555 self.TV_sgProp = Property(ACE_NS.TV_sg, | |
556 baseType=OWL_NS.AnnotationProperty, | |
557 graph=self.graph) | |
558 | |
559 # plural form of a transitive verb | |
560 self.TV_plProp = Property(ACE_NS.TV_pl, | |
561 baseType=OWL_NS.AnnotationProperty, | |
562 graph=self.graph) | |
563 | |
564 # past participle form a transitive verb | |
565 self.TV_vbgProp = Property(ACE_NS.TV_vbg, | |
566 baseType=OWL_NS.AnnotationProperty, | |
567 graph=self.graph) | |
568 | |
569 def _get_comment(self): | |
570 for comment in self.graph.objects( | |
571 subject=self.identifier, predicate=RDFS.comment): | |
572 yield comment | |
573 | |
574 def _set_comment(self, comment): | |
575 if not comment: | |
576 return | |
577 if isinstance(comment, Identifier): | |
578 self.graph.add((self.identifier, RDFS.comment, comment)) | |
579 else: | |
580 for c in comment: | |
581 self.graph.add((self.identifier, RDFS.comment, c)) | |
582 | |
583 @TermDeletionHelper(RDFS.comment) | |
584 def _del_comment(self): | |
585 pass | |
586 | |
587 comment = property(_get_comment, _set_comment, _del_comment) | |
588 | |
589 def _get_seeAlso(self): | |
590 for sA in self.graph.objects( | |
591 subject=self.identifier, predicate=RDFS.seeAlso): | |
592 yield sA | |
593 | |
594 def _set_seeAlso(self, seeAlsos): | |
595 if not seeAlsos: | |
596 return | |
597 for s in seeAlsos: | |
598 self.graph.add((self.identifier, RDFS.seeAlso, s)) | |
599 | |
600 @TermDeletionHelper(RDFS.seeAlso) | |
601 def _del_seeAlso(self): | |
602 pass | |
603 seeAlso = property(_get_seeAlso, _set_seeAlso, _del_seeAlso) | |
604 | |
605 def _get_label(self): | |
606 for label in self.graph.objects( | |
607 subject=self.identifier, predicate=RDFS.label): | |
608 yield label | |
609 | |
610 def _set_label(self, label): | |
611 if not label: | |
612 return | |
613 if isinstance(label, Identifier): | |
614 self.graph.add((self.identifier, RDFS.label, label)) | |
615 else: | |
616 for l in label: | |
617 self.graph.add((self.identifier, RDFS.label, l)) | |
618 | |
619 @TermDeletionHelper(RDFS.label) | |
620 def _delete_label(self): | |
621 """ | |
622 >>> g=Graph() | |
623 >>> b=Individual(OWL_NS.Restriction,g) | |
624 >>> b.label = Literal('boo') | |
625 >>> len(list(b.label)) | |
626 1 | |
627 >>> del b.label | |
628 >>> len(list(b.label)) | |
629 0 | |
630 """ | |
631 pass | |
632 | |
633 label = property(_get_label, _set_label, _delete_label) | |
634 | |
635 | |
636 class Ontology(AnnotatableTerms): | |
637 """ The owl ontology metadata""" | |
638 | |
639 def __init__(self, | |
640 identifier=None, imports=None, comment=None, graph=None): | |
641 super(Ontology, self).__init__(identifier, graph) | |
642 self.imports = imports and imports or [] | |
643 self.comment = comment and comment or [] | |
644 if (self.identifier, RDF.type, OWL_NS.Ontology) not in self.graph: | |
645 self.graph.add((self.identifier, RDF.type, OWL_NS.Ontology)) | |
646 | |
647 def setVersion(self, version): | |
648 self.graph.set((self.identifier, OWL_NS.versionInfo, version)) | |
649 | |
650 def _get_imports(self): | |
651 for owl in self.graph.objects( | |
652 subject=self.identifier, predicate=OWL_NS['imports']): | |
653 yield owl | |
654 | |
655 def _set_imports(self, other): | |
656 if not other: | |
657 return | |
658 for o in other: | |
659 self.graph.add((self.identifier, OWL_NS['imports'], o)) | |
660 | |
661 @TermDeletionHelper(OWL_NS['imports']) | |
662 def _del_imports(self): | |
663 pass | |
664 | |
665 imports = property(_get_imports, _set_imports, _del_imports) | |
666 | |
667 | |
668 def AllClasses(graph): | |
669 prevClasses = set() | |
670 for c in graph.subjects(predicate=RDF.type, object=OWL_NS.Class): | |
671 if c not in prevClasses: | |
672 prevClasses.add(c) | |
673 yield Class(c) | |
674 | |
675 | |
676 def AllProperties(graph): | |
677 prevProps = set() | |
678 for s, p, o in graph.triples_choices( | |
679 (None, RDF.type, [OWL_NS.SymmetricProperty, | |
680 OWL_NS.FunctionalProperty, | |
681 OWL_NS.InverseFunctionalProperty, | |
682 OWL_NS.TransitiveProperty, | |
683 OWL_NS.DatatypeProperty, | |
684 OWL_NS.ObjectProperty, | |
685 OWL_NS.AnnotationProperty])): | |
686 if o in [OWL_NS.SymmetricProperty, | |
687 OWL_NS.InverseFunctionalProperty, | |
688 OWL_NS.TransitiveProperty, | |
689 OWL_NS.ObjectProperty]: | |
690 bType = OWL_NS.ObjectProperty | |
691 else: | |
692 bType = OWL_NS.DatatypeProperty | |
693 if s not in prevProps: | |
694 prevProps.add(s) | |
695 yield Property(s, | |
696 graph=graph, | |
697 baseType=bType) | |
698 | |
699 | |
700 class ClassNamespaceFactory(Namespace): | |
701 def term(self, name): | |
702 return Class(URIRef(self + name)) | |
703 | |
704 def __getitem__(self, key, default=None): | |
705 return self.term(key) | |
706 | |
707 def __getattr__(self, name): | |
708 if name.startswith("__"): # ignore any special Python names! | |
709 raise AttributeError | |
710 else: | |
711 return self.term(name) | |
712 | |
713 | |
714 CLASS_RELATIONS = set( | |
715 OWL_NS.resourceProperties | |
716 ).difference([OWL_NS.onProperty, | |
717 OWL_NS.allValuesFrom, | |
718 OWL_NS.hasValue, | |
719 OWL_NS.someValuesFrom, | |
720 OWL_NS.inverseOf, | |
721 OWL_NS.imports, | |
722 OWL_NS.versionInfo, | |
723 OWL_NS.backwardCompatibleWith, | |
724 OWL_NS.incompatibleWith, | |
725 OWL_NS.unionOf, | |
726 OWL_NS.intersectionOf, | |
727 OWL_NS.oneOf]) | |
728 | |
729 | |
730 def ComponentTerms(cls): | |
731 """ | |
732 Takes a Class instance and returns a generator over the classes that | |
733 are involved in its definition, ignoring unnamed classes | |
734 """ | |
735 if OWL_NS.Restriction in cls.type: | |
736 try: | |
737 cls = CastClass(cls, Individual.factoryGraph) | |
738 for s, p, innerClsId in cls.factoryGraph.triples_choices( | |
739 (cls.identifier, | |
740 [OWL_NS.allValuesFrom, | |
741 OWL_NS.someValuesFrom], | |
742 None)): | |
743 innerCls = Class(innerClsId, skipOWLClassMembership=True) | |
744 if isinstance(innerClsId, BNode): | |
745 for _c in ComponentTerms(innerCls): | |
746 yield _c | |
747 else: | |
748 yield innerCls | |
749 except: | |
750 pass | |
751 else: | |
752 cls = CastClass(cls, Individual.factoryGraph) | |
753 if isinstance(cls, BooleanClass): | |
754 for _cls in cls: | |
755 _cls = Class(_cls, skipOWLClassMembership=True) | |
756 if isinstance(_cls.identifier, BNode): | |
757 for _c in ComponentTerms(_cls): | |
758 yield _c | |
759 else: | |
760 yield _cls | |
761 else: | |
762 for innerCls in cls.subClassOf: | |
763 if isinstance(innerCls.identifier, BNode): | |
764 for _c in ComponentTerms(innerCls): | |
765 yield _c | |
766 else: | |
767 yield innerCls | |
768 for s, p, o in cls.factoryGraph.triples_choices( | |
769 (classOrIdentifier(cls), | |
770 CLASS_RELATIONS, | |
771 None) | |
772 ): | |
773 if isinstance(o, BNode): | |
774 for _c in ComponentTerms( | |
775 CastClass(o, Individual.factoryGraph)): | |
776 yield _c | |
777 else: | |
778 yield innerCls | |
779 | |
780 | |
781 def DeepClassClear(classToPrune): | |
782 """ | |
783 Recursively clear the given class, continuing | |
784 where any related class is an anonymous class | |
785 | |
786 >>> EX = Namespace('http://example.com/') | |
787 >>> namespace_manager = NamespaceManager(Graph()) | |
788 >>> namespace_manager.bind('ex', EX, override=False) | |
789 >>> namespace_manager.bind('owl', OWL_NS, override=False) | |
790 >>> g = Graph() | |
791 >>> g.namespace_manager = namespace_manager | |
792 >>> Individual.factoryGraph = g | |
793 >>> classB = Class(EX.B) | |
794 >>> classC = Class(EX.C) | |
795 >>> classD = Class(EX.D) | |
796 >>> classE = Class(EX.E) | |
797 >>> classF = Class(EX.F) | |
798 >>> anonClass = EX.someProp | some | classD #doctest: +SKIP | |
799 >>> classF += anonClass #doctest: +SKIP | |
800 >>> list(anonClass.subClassOf) #doctest: +SKIP | |
801 [Class: ex:F ] | |
802 >>> classA = classE | classF | anonClass #doctest: +SKIP | |
803 >>> classB += classA #doctest: +SKIP | |
804 >>> classA.equivalentClass = [Class()] #doctest: +SKIP | |
805 >>> classB.subClassOf = [EX.someProp | some | classC] #doctest: +SKIP | |
806 >>> classA #doctest: +SKIP | |
807 ( ex:E OR ex:F OR ( ex:someProp SOME ex:D ) ) | |
808 >>> DeepClassClear(classA) #doctest: +SKIP | |
809 >>> classA #doctest: +SKIP | |
810 ( ) | |
811 >>> list(anonClass.subClassOf) #doctest: +SKIP | |
812 [] | |
813 >>> classB #doctest: +SKIP | |
814 Class: ex:B SubClassOf: ( ex:someProp SOME ex:C ) | |
815 | |
816 >>> otherClass = classD | anonClass #doctest: +SKIP | |
817 >>> otherClass #doctest: +SKIP | |
818 ( ex:D OR ( ex:someProp SOME ex:D ) ) | |
819 >>> DeepClassClear(otherClass) #doctest: +SKIP | |
820 >>> otherClass #doctest: +SKIP | |
821 ( ) | |
822 >>> otherClass.delete() #doctest: +SKIP | |
823 >>> list(g.triples((otherClass.identifier, None, None))) #doctest: +SKIP | |
824 [] | |
825 """ | |
826 def deepClearIfBNode(_class): | |
827 if isinstance(classOrIdentifier(_class), BNode): | |
828 DeepClassClear(_class) | |
829 classToPrune = CastClass(classToPrune, Individual.factoryGraph) | |
830 for c in classToPrune.subClassOf: | |
831 deepClearIfBNode(c) | |
832 classToPrune.graph.remove((classToPrune.identifier, RDFS.subClassOf, None)) | |
833 for c in classToPrune.equivalentClass: | |
834 deepClearIfBNode(c) | |
835 classToPrune.graph.remove( | |
836 (classToPrune.identifier, OWL_NS.equivalentClass, None)) | |
837 inverseClass = classToPrune.complementOf | |
838 if inverseClass: | |
839 classToPrune.graph.remove( | |
840 (classToPrune.identifier, OWL_NS.complementOf, None)) | |
841 deepClearIfBNode(inverseClass) | |
842 if isinstance(classToPrune, BooleanClass): | |
843 for c in classToPrune: | |
844 deepClearIfBNode(c) | |
845 classToPrune.clear() | |
846 classToPrune.graph.remove((classToPrune.identifier, | |
847 classToPrune._operator, | |
848 None)) | |
849 | |
850 | |
851 class MalformedClass(Exception): | |
852 def __init__(self, msg): | |
853 self.msg = msg | |
854 | |
855 def __repr__(self): | |
856 return self.msg | |
857 | |
858 | |
859 def CastClass(c, graph=None): | |
860 graph = graph is None and c.factoryGraph or graph | |
861 for kind in graph.objects(subject=classOrIdentifier(c), | |
862 predicate=RDF.type): | |
863 if kind == OWL_NS.Restriction: | |
864 kwArgs = {'identifier': classOrIdentifier(c), | |
865 'graph': graph} | |
866 for s, p, o in graph.triples((classOrIdentifier(c), | |
867 None, | |
868 None)): | |
869 if p != RDF.type: | |
870 if p == OWL_NS.onProperty: | |
871 kwArgs['onProperty'] = o | |
872 else: | |
873 if p not in Restriction.restrictionKinds: | |
874 continue | |
875 kwArgs[str(p.split(OWL_NS)[-1])] = o | |
876 if not set([str(i.split(OWL_NS)[-1]) | |
877 for i in Restriction.restrictionKinds] | |
878 ).intersection(kwArgs): | |
879 raise MalformedClass("Malformed owl:Restriction") | |
880 return Restriction(**kwArgs) | |
881 else: | |
882 for s, p, o in graph.triples_choices((classOrIdentifier(c), | |
883 [OWL_NS.intersectionOf, | |
884 OWL_NS.unionOf, | |
885 OWL_NS.oneOf], | |
886 None)): | |
887 if p == OWL_NS.oneOf: | |
888 return EnumeratedClass(classOrIdentifier(c), graph=graph) | |
889 else: | |
890 return BooleanClass( | |
891 classOrIdentifier(c), operator=p, graph=graph) | |
892 # assert (classOrIdentifier(c),RDF.type,OWL_NS.Class) in graph | |
893 return Class( | |
894 classOrIdentifier(c), graph=graph, skipOWLClassMembership=True) | |
895 | |
896 | |
897 class Class(AnnotatableTerms): | |
898 """ | |
899 'General form' for classes: | |
900 | |
901 The Manchester Syntax (supported in Protege) is used as the basis for the | |
902 form of this class | |
903 | |
904 See: http://owl-workshop.man.ac.uk/acceptedLong/submission_9.pdf: | |
905 | |
906 [Annotation] | |
907 ‘Class:’ classID {Annotation | |
908 ( (‘SubClassOf:’ ClassExpression) | |
909 | (‘EquivalentTo’ ClassExpression) | |
910 | (’DisjointWith’ ClassExpression)) } | |
911 | |
912 Appropriate excerpts from OWL Reference: | |
913 | |
914 ".. Subclass axioms provide us with partial definitions: they represent | |
915 necessary but not sufficient conditions for establishing class | |
916 membership of an individual." | |
917 | |
918 ".. A class axiom may contain (multiple) owl:equivalentClass statements" | |
919 | |
920 "..A class axiom may also contain (multiple) owl:disjointWith statements.." | |
921 | |
922 "..An owl:complementOf property links a class to precisely one class | |
923 description." | |
924 | |
925 """ | |
926 | |
927 def _serialize(self, graph): | |
928 for cl in self.subClassOf: | |
929 CastClass(cl, self.graph).serialize(graph) | |
930 for cl in self.equivalentClass: | |
931 CastClass(cl, self.graph).serialize(graph) | |
932 for cl in self.disjointWith: | |
933 CastClass(cl, self.graph).serialize(graph) | |
934 if self.complementOf: | |
935 CastClass(self.complementOf, self.graph).serialize(graph) | |
936 | |
937 def serialize(self, graph): | |
938 for fact in self.graph.triples((self.identifier, None, None)): | |
939 graph.add(fact) | |
940 self._serialize(graph) | |
941 | |
942 def setupNounAnnotations(self, nounAnnotations): | |
943 if isinstance(nounAnnotations, tuple): | |
944 CN_sgProp, CN_plProp = nounAnnotations | |
945 else: | |
946 CN_sgProp = nounAnnotations | |
947 CN_plProp = nounAnnotations | |
948 | |
949 if CN_sgProp: | |
950 self.CN_sgProp.extent = [(self.identifier, | |
951 self.handleAnnotation(CN_sgProp))] | |
952 if CN_plProp: | |
953 self.CN_plProp.extent = [(self.identifier, | |
954 self.handleAnnotation(CN_plProp))] | |
955 | |
956 def __init__(self, identifier=None, subClassOf=None, equivalentClass=None, | |
957 disjointWith=None, complementOf=None, graph=None, | |
958 skipOWLClassMembership=False, comment=None, | |
959 nounAnnotations=None, | |
960 nameAnnotation=None, | |
961 nameIsLabel=False): | |
962 super(Class, self).__init__(identifier, graph, | |
963 nameAnnotation, nameIsLabel) | |
964 | |
965 if nounAnnotations: | |
966 self.setupNounAnnotations(nounAnnotations) | |
967 if not skipOWLClassMembership \ | |
968 and (self.identifier, RDF.type, OWL_NS.Class) \ | |
969 not in self.graph and \ | |
970 (self.identifier, RDF.type, OWL_NS.Restriction) \ | |
971 not in self.graph: | |
972 self.graph.add((self.identifier, RDF.type, OWL_NS.Class)) | |
973 | |
974 self.subClassOf = subClassOf and subClassOf or [] | |
975 self.equivalentClass = equivalentClass and equivalentClass or [] | |
976 self.disjointWith = disjointWith and disjointWith or [] | |
977 if complementOf: | |
978 self.complementOf = complementOf | |
979 self.comment = comment and comment or [] | |
980 | |
981 def _get_extent(self, graph=None): | |
982 for member in ( | |
983 graph is None and self.graph or graph).subjects( | |
984 predicate=RDF.type, object=self.identifier): | |
985 yield member | |
986 | |
987 def _set_extent(self, other): | |
988 if not other: | |
989 return | |
990 for m in other: | |
991 self.graph.add((classOrIdentifier(m), RDF.type, self.identifier)) | |
992 | |
993 @TermDeletionHelper(RDF.type) | |
994 def _del_type(self): | |
995 pass | |
996 | |
997 extent = property(_get_extent, _set_extent, _del_type) | |
998 | |
999 def _get_annotation(self, term=RDFS.label): | |
1000 for annotation in self.graph.objects(subject=self, predicate=term): | |
1001 yield annotation | |
1002 | |
1003 annotation = property(_get_annotation, lambda x: x) | |
1004 | |
1005 def _get_extentQuery(self): | |
1006 return (Variable('CLASS'), RDF.type, self.identifier) | |
1007 | |
1008 def _set_extentQuery(self, other): | |
1009 pass | |
1010 | |
1011 extentQuery = property(_get_extentQuery, _set_extentQuery) | |
1012 | |
1013 def __hash__(self): | |
1014 """ | |
1015 >>> b=Class(OWL_NS.Restriction) | |
1016 >>> c=Class(OWL_NS.Restriction) | |
1017 >>> len(set([b,c])) | |
1018 1 | |
1019 """ | |
1020 return hash(self.identifier) | |
1021 | |
1022 def __eq__(self, other): | |
1023 assert isinstance(other, Class), repr(other) | |
1024 return self.identifier == other.identifier | |
1025 | |
1026 def __iadd__(self, other): | |
1027 assert isinstance(other, Class) | |
1028 other.subClassOf = [self] | |
1029 return self | |
1030 | |
1031 def __isub__(self, other): | |
1032 assert isinstance(other, Class) | |
1033 self.graph.remove( | |
1034 (classOrIdentifier(other), RDFS.subClassOf, self.identifier)) | |
1035 return self | |
1036 | |
1037 def __invert__(self): | |
1038 """ | |
1039 Shorthand for Manchester syntax's not operator | |
1040 """ | |
1041 return Class(complementOf=self) | |
1042 | |
1043 def __or__(self, other): | |
1044 """ | |
1045 Construct an anonymous class description consisting of the union of | |
1046 this class and 'other' and return it | |
1047 """ | |
1048 return BooleanClass( | |
1049 operator=OWL_NS.unionOf, members=[self, other], graph=self.graph) | |
1050 | |
1051 def __and__(self, other): | |
1052 """ | |
1053 Construct an anonymous class description consisting of the | |
1054 intersection of this class and 'other' and return it | |
1055 | |
1056 >>> exNs = Namespace('http://example.com/') | |
1057 >>> namespace_manager = NamespaceManager(Graph()) | |
1058 >>> namespace_manager.bind('ex', exNs, override=False) | |
1059 >>> namespace_manager.bind('owl', OWL_NS, override=False) | |
1060 >>> g = Graph() | |
1061 >>> g.namespace_manager = namespace_manager | |
1062 | |
1063 Chaining 3 intersections | |
1064 | |
1065 >>> female = Class(exNs.Female, graph=g) | |
1066 >>> human = Class(exNs.Human, graph=g) | |
1067 >>> youngPerson = Class(exNs.YoungPerson, graph=g) | |
1068 >>> youngWoman = female & human & youngPerson | |
1069 >>> youngWoman #doctest: +SKIP | |
1070 ex:YoungPerson THAT ( ex:Female AND ex:Human ) | |
1071 >>> isinstance(youngWoman, BooleanClass) | |
1072 True | |
1073 >>> isinstance(youngWoman.identifier, BNode) | |
1074 True | |
1075 """ | |
1076 return BooleanClass( | |
1077 operator=OWL_NS.intersectionOf, | |
1078 members=[self, other], graph=self.graph) | |
1079 | |
1080 def _get_subClassOf(self): | |
1081 for anc in self.graph.objects( | |
1082 subject=self.identifier, predicate=RDFS.subClassOf): | |
1083 yield Class(anc, | |
1084 graph=self.graph, | |
1085 skipOWLClassMembership=True) | |
1086 | |
1087 def _set_subClassOf(self, other): | |
1088 if not other: | |
1089 return | |
1090 for sc in other: | |
1091 self.graph.add( | |
1092 (self.identifier, RDFS.subClassOf, classOrIdentifier(sc))) | |
1093 | |
1094 @TermDeletionHelper(RDFS.subClassOf) | |
1095 def _del_subClassOf(self): | |
1096 pass | |
1097 | |
1098 subClassOf = property(_get_subClassOf, _set_subClassOf, _del_subClassOf) | |
1099 | |
1100 def _get_equivalentClass(self): | |
1101 for ec in self.graph.objects( | |
1102 subject=self.identifier, predicate=OWL_NS.equivalentClass): | |
1103 yield Class(ec, graph=self.graph) | |
1104 | |
1105 def _set_equivalentClass(self, other): | |
1106 if not other: | |
1107 return | |
1108 for sc in other: | |
1109 self.graph.add((self.identifier, | |
1110 OWL_NS.equivalentClass, classOrIdentifier(sc))) | |
1111 | |
1112 @TermDeletionHelper(OWL_NS.equivalentClass) | |
1113 def _del_equivalentClass(self): | |
1114 pass | |
1115 | |
1116 equivalentClass = property( | |
1117 _get_equivalentClass, _set_equivalentClass, _del_equivalentClass) | |
1118 | |
1119 def _get_disjointWith(self): | |
1120 for dc in self.graph.objects( | |
1121 subject=self.identifier, predicate=OWL_NS.disjointWith): | |
1122 yield Class(dc, graph=self.graph) | |
1123 | |
1124 def _set_disjointWith(self, other): | |
1125 if not other: | |
1126 return | |
1127 for c in other: | |
1128 self.graph.add( | |
1129 (self.identifier, OWL_NS.disjointWith, classOrIdentifier(c))) | |
1130 | |
1131 @TermDeletionHelper(OWL_NS.disjointWith) | |
1132 def _del_disjointWith(self): | |
1133 pass | |
1134 | |
1135 disjointWith = property( | |
1136 _get_disjointWith, _set_disjointWith, _del_disjointWith) | |
1137 | |
1138 def _get_complementOf(self): | |
1139 comp = list(self.graph.objects( | |
1140 subject=self.identifier, predicate=OWL_NS.complementOf)) | |
1141 if not comp: | |
1142 return None | |
1143 elif len(comp) == 1: | |
1144 return Class(comp[0], graph=self.graph) | |
1145 else: | |
1146 raise Exception(len(comp)) | |
1147 | |
1148 def _set_complementOf(self, other): | |
1149 if not other: | |
1150 return | |
1151 self.graph.add( | |
1152 (self.identifier, OWL_NS.complementOf, classOrIdentifier(other))) | |
1153 | |
1154 @TermDeletionHelper(OWL_NS.complementOf) | |
1155 def _del_complementOf(self): | |
1156 pass | |
1157 | |
1158 complementOf = property( | |
1159 _get_complementOf, _set_complementOf, _del_complementOf) | |
1160 | |
1161 def _get_parents(self): | |
1162 """ | |
1163 computed attributes that returns a generator over taxonomic 'parents' | |
1164 by disjunction, conjunction, and subsumption | |
1165 | |
1166 >>> from rdflib.util import first | |
1167 >>> exNs = Namespace('http://example.com/') | |
1168 >>> namespace_manager = NamespaceManager(Graph()) | |
1169 >>> namespace_manager.bind('ex', exNs, override=False) | |
1170 >>> namespace_manager.bind('owl', OWL_NS, override=False) | |
1171 >>> g = Graph() | |
1172 >>> g.namespace_manager = namespace_manager | |
1173 >>> Individual.factoryGraph = g | |
1174 >>> brother = Class(exNs.Brother) | |
1175 >>> sister = Class(exNs.Sister) | |
1176 >>> sibling = brother | sister | |
1177 >>> sibling.identifier = exNs.Sibling | |
1178 >>> sibling #doctest: +SKIP | |
1179 ( ex:Brother OR ex:Sister ) | |
1180 >>> first(brother.parents) #doctest: +SKIP | |
1181 Class: ex:Sibling EquivalentTo: ( ex:Brother OR ex:Sister ) | |
1182 >>> parent = Class(exNs.Parent) | |
1183 >>> male = Class(exNs.Male) | |
1184 >>> father = parent & male | |
1185 >>> father.identifier = exNs.Father | |
1186 >>> list(father.parents) #doctest: +SKIP | |
1187 [Class: ex:Parent , Class: ex:Male ] | |
1188 | |
1189 """ | |
1190 for parent in itertools.chain(self.subClassOf, | |
1191 self.equivalentClass): | |
1192 yield parent | |
1193 | |
1194 link = first(self.factoryGraph.subjects(RDF.first, self.identifier)) | |
1195 if link: | |
1196 listSiblings = list(self.factoryGraph.transitive_subjects(RDF.rest, | |
1197 link)) | |
1198 if listSiblings: | |
1199 collectionHead = listSiblings[-1] | |
1200 else: | |
1201 collectionHead = link | |
1202 for disjCls in self.factoryGraph.subjects( | |
1203 OWL_NS.unionOf, collectionHead): | |
1204 if isinstance(disjCls, URIRef): | |
1205 yield Class(disjCls, skipOWLClassMembership=True) | |
1206 for rdfList in self.factoryGraph.objects( | |
1207 self.identifier, OWL_NS.intersectionOf): | |
1208 for member in OWLRDFListProxy([rdfList], graph=self.factoryGraph): | |
1209 if isinstance(member, URIRef): | |
1210 yield Class(member, skipOWLClassMembership=True) | |
1211 | |
1212 parents = property(_get_parents) | |
1213 | |
1214 def isPrimitive(self): | |
1215 if (self.identifier, RDF.type, OWL_NS.Restriction) in self.graph: | |
1216 return False | |
1217 # sc = list(self.subClassOf) | |
1218 ec = list(self.equivalentClass) | |
1219 for boolClass, p, rdfList in self.graph.triples_choices( | |
1220 (self.identifier, | |
1221 [OWL_NS.intersectionOf, | |
1222 OWL_NS.unionOf], | |
1223 None)): | |
1224 ec.append(manchesterSyntax(rdfList, self.graph, boolean=p)) | |
1225 for e in ec: | |
1226 return False | |
1227 if self.complementOf: | |
1228 return False | |
1229 return True | |
1230 | |
1231 def subSumpteeIds(self): | |
1232 for s in self.graph.subjects( | |
1233 predicate=RDFS.subClassOf, object=self.identifier): | |
1234 yield s | |
1235 | |
1236 # def __iter__(self): | |
1237 # for s in self.graph.subjects( | |
1238 # predicate=RDFS.subClassOf,object=self.identifier): | |
1239 # yield Class(s,skipOWLClassMembership=True) | |
1240 | |
1241 def __repr__(self, full=False, normalization=True): | |
1242 """ | |
1243 Returns the Manchester Syntax equivalent for this class | |
1244 """ | |
1245 exprs = [] | |
1246 sc = list(self.subClassOf) | |
1247 ec = list(self.equivalentClass) | |
1248 for boolClass, p, rdfList in self.graph.triples_choices( | |
1249 (self.identifier, | |
1250 [OWL_NS.intersectionOf, | |
1251 OWL_NS.unionOf], | |
1252 None)): | |
1253 ec.append(manchesterSyntax(rdfList, self.graph, boolean=p)) | |
1254 dc = list(self.disjointWith) | |
1255 c = self.complementOf | |
1256 if c: | |
1257 dc.append(c) | |
1258 klassKind = '' | |
1259 label = list(self.graph.objects(self.identifier, RDFS.label)) | |
1260 label = label and '(' + label[0] + ')' or '' | |
1261 if sc: | |
1262 if full: | |
1263 scJoin = '\n ' | |
1264 else: | |
1265 scJoin = ', ' | |
1266 necStatements = [ | |
1267 isinstance(s, Class) and isinstance(self.identifier, BNode) | |
1268 and repr(CastClass(s, self.graph)) or | |
1269 # repr(BooleanClass(classOrIdentifier(s), | |
1270 # operator=None, | |
1271 # graph=self.graph)) or | |
1272 manchesterSyntax(classOrIdentifier(s), self.graph) for s in sc] | |
1273 if necStatements: | |
1274 klassKind = "Primitive Type %s" % label | |
1275 exprs.append("SubClassOf: %s" % scJoin.join( | |
1276 [str(n) for n in necStatements])) | |
1277 if full: | |
1278 exprs[-1] = "\n " + exprs[-1] | |
1279 if ec: | |
1280 nec_SuffStatements = [ | |
1281 isinstance(s, str) and s | |
1282 or manchesterSyntax(classOrIdentifier(s), self.graph) for s in ec] | |
1283 if nec_SuffStatements: | |
1284 klassKind = "A Defined Class %s" % label | |
1285 exprs.append("EquivalentTo: %s" % ', '.join(nec_SuffStatements)) | |
1286 if full: | |
1287 exprs[-1] = "\n " + exprs[-1] | |
1288 if dc: | |
1289 exprs.append("DisjointWith %s\n" % '\n '.join( | |
1290 [manchesterSyntax(classOrIdentifier(s), self.graph) | |
1291 for s in dc])) | |
1292 if full: | |
1293 exprs[-1] = "\n " + exprs[-1] | |
1294 descr = list(self.graph.objects(self.identifier, RDFS.comment)) | |
1295 if full and normalization: | |
1296 klassDescr = klassKind and '\n ## %s ##' % klassKind +\ | |
1297 (descr and "\n %s" % descr[0] or '') + \ | |
1298 ' . '.join(exprs) or ' . '.join(exprs) | |
1299 else: | |
1300 klassDescr = full and (descr and "\n %s" % | |
1301 descr[0] or '') or '' + ' . '.join(exprs) | |
1302 return (isinstance(self.identifier, BNode) and | |
1303 "Some Class " or | |
1304 "Class: %s " % self.qname) + klassDescr | |
1305 | |
1306 | |
1307 class OWLRDFListProxy(object): | |
1308 def __init__(self, rdfList, members=None, graph=None): | |
1309 if graph: | |
1310 self.graph = graph | |
1311 members = members and members or [] | |
1312 if rdfList: | |
1313 self._rdfList = Collection(self.graph, rdfList[0]) | |
1314 for member in members: | |
1315 if member not in self._rdfList: | |
1316 self._rdfList.append(classOrIdentifier(member)) | |
1317 else: | |
1318 self._rdfList = Collection(self.graph, BNode(), | |
1319 [classOrIdentifier(m) for m in members]) | |
1320 self.graph.add( | |
1321 (self.identifier, self._operator, self._rdfList.uri)) | |
1322 | |
1323 def __eq__(self, other): | |
1324 """ | |
1325 Equivalence of boolean class constructors is determined by | |
1326 equivalence of its members | |
1327 """ | |
1328 assert isinstance(other, Class), repr(other) + repr(type(other)) | |
1329 if isinstance(other, BooleanClass): | |
1330 length = len(self) | |
1331 if length != len(other): | |
1332 return False | |
1333 else: | |
1334 for idx in range(length): | |
1335 if self[idx] != other[idx]: | |
1336 return False | |
1337 return True | |
1338 else: | |
1339 return self.identifier == other.identifier | |
1340 | |
1341 # Redirect python list accessors to the underlying Collection instance | |
1342 def __len__(self): | |
1343 return len(self._rdfList) | |
1344 | |
1345 def index(self, item): | |
1346 return self._rdfList.index(classOrIdentifier(item)) | |
1347 | |
1348 def __getitem__(self, key): | |
1349 return self._rdfList[key] | |
1350 | |
1351 def __setitem__(self, key, value): | |
1352 self._rdfList[key] = classOrIdentifier(value) | |
1353 | |
1354 def __delitem__(self, key): | |
1355 del self._rdfList[key] | |
1356 | |
1357 def clear(self): | |
1358 self._rdfList.clear() | |
1359 | |
1360 def __iter__(self): | |
1361 for item in self._rdfList: | |
1362 yield item | |
1363 | |
1364 def __contains__(self, item): | |
1365 for i in self._rdfList: | |
1366 if i == classOrIdentifier(item): | |
1367 return 1 | |
1368 return 0 | |
1369 | |
1370 def append(self, item): | |
1371 self._rdfList.append(item) | |
1372 | |
1373 def __iadd__(self, other): | |
1374 self._rdfList.append(classOrIdentifier(other)) | |
1375 return self | |
1376 | |
1377 | |
1378 class EnumeratedClass(OWLRDFListProxy, Class): | |
1379 """ | |
1380 Class for owl:oneOf forms: | |
1381 | |
1382 OWL Abstract Syntax is used | |
1383 | |
1384 axiom ::= 'EnumeratedClass(' | |
1385 classID ['Deprecated'] { annotation } { individualID } ')' | |
1386 | |
1387 | |
1388 >>> exNs = Namespace('http://example.com/') | |
1389 >>> namespace_manager = NamespaceManager(Graph()) | |
1390 >>> namespace_manager.bind('ex', exNs, override=False) | |
1391 >>> namespace_manager.bind('owl', OWL_NS, override=False) | |
1392 >>> g = Graph() | |
1393 >>> g.namespace_manager = namespace_manager | |
1394 >>> Individual.factoryGraph = g | |
1395 >>> ogbujiBros = EnumeratedClass(exNs.ogbujicBros, | |
1396 ... members=[exNs.chime, | |
1397 ... exNs.uche, | |
1398 ... exNs.ejike]) | |
1399 >>> ogbujiBros #doctest: +SKIP | |
1400 { ex:chime ex:uche ex:ejike } | |
1401 >>> col = Collection(g, first( | |
1402 ... g.objects(predicate=OWL_NS.oneOf, subject=ogbujiBros.identifier))) | |
1403 >>> [g.qname(item) for item in col] | |
1404 [u'ex:chime', u'ex:uche', u'ex:ejike'] | |
1405 >>> print(g.serialize(format='n3')) #doctest: +SKIP | |
1406 @prefix ex: <http://example.com/> . | |
1407 @prefix owl: <http://www.w3.org/2002/07/owl#> . | |
1408 @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . | |
1409 <BLANKLINE> | |
1410 ex:ogbujicBros a owl:Class; | |
1411 owl:oneOf ( ex:chime ex:uche ex:ejike ) . | |
1412 <BLANKLINE> | |
1413 <BLANKLINE> | |
1414 """ | |
1415 _operator = OWL_NS.oneOf | |
1416 | |
1417 def isPrimitive(self): | |
1418 return False | |
1419 | |
1420 def __init__(self, identifier=None, members=None, graph=None): | |
1421 Class.__init__(self, identifier, graph=graph) | |
1422 members = members and members or [] | |
1423 rdfList = list(self.graph.objects( | |
1424 predicate=OWL_NS.oneOf, subject=self.identifier)) | |
1425 OWLRDFListProxy.__init__(self, rdfList, members) | |
1426 | |
1427 def __repr__(self): | |
1428 """ | |
1429 Returns the Manchester Syntax equivalent for this class | |
1430 """ | |
1431 return manchesterSyntax( | |
1432 self._rdfList.uri, self.graph, boolean=self._operator) | |
1433 | |
1434 def serialize(self, graph): | |
1435 clonedList = Collection(graph, BNode()) | |
1436 for cl in self._rdfList: | |
1437 clonedList.append(cl) | |
1438 CastClass(cl, self.graph).serialize(graph) | |
1439 | |
1440 graph.add((self.identifier, self._operator, clonedList.uri)) | |
1441 for s, p, o in self.graph.triples((self.identifier, None, None)): | |
1442 if p != self._operator: | |
1443 graph.add((s, p, o)) | |
1444 self._serialize(graph) | |
1445 | |
1446 | |
1447 BooleanPredicates = [OWL_NS.intersectionOf, OWL_NS.unionOf] | |
1448 | |
1449 | |
1450 class BooleanClassExtentHelper: | |
1451 """ | |
1452 >>> testGraph = Graph() | |
1453 >>> Individual.factoryGraph = testGraph | |
1454 >>> EX = Namespace("http://example.com/") | |
1455 >>> namespace_manager = NamespaceManager(Graph()) | |
1456 >>> namespace_manager.bind('ex', EX, override=False) | |
1457 >>> testGraph.namespace_manager = namespace_manager | |
1458 >>> fire = Class(EX.Fire) | |
1459 >>> water = Class(EX.Water) | |
1460 >>> testClass = BooleanClass(members=[fire, water]) | |
1461 >>> testClass2 = BooleanClass( | |
1462 ... operator=OWL_NS.unionOf, members=[fire, water]) | |
1463 >>> for c in BooleanClass.getIntersections(): | |
1464 ... print(c) #doctest: +SKIP | |
1465 ( ex:Fire AND ex:Water ) | |
1466 >>> for c in BooleanClass.getUnions(): | |
1467 ... print(c) #doctest: +SKIP | |
1468 ( ex:Fire OR ex:Water ) | |
1469 """ | |
1470 | |
1471 def __init__(self, operator): | |
1472 self.operator = operator | |
1473 | |
1474 def __call__(self, f): | |
1475 def _getExtent(): | |
1476 for c in Individual.factoryGraph.subjects(self.operator): | |
1477 yield BooleanClass(c, operator=self.operator) | |
1478 return _getExtent | |
1479 | |
1480 | |
1481 class Callable(): | |
1482 def __init__(self, anycallable): | |
1483 self.__call__ = anycallable | |
1484 | |
1485 | |
1486 class BooleanClass(OWLRDFListProxy, Class): | |
1487 """ | |
1488 See: http://www.w3.org/TR/owl-ref/#Boolean | |
1489 | |
1490 owl:complementOf is an attribute of Class, however | |
1491 | |
1492 """ | |
1493 @BooleanClassExtentHelper(OWL_NS.intersectionOf) | |
1494 @Callable | |
1495 def getIntersections(): | |
1496 pass | |
1497 getIntersections = Callable(getIntersections) | |
1498 | |
1499 @BooleanClassExtentHelper(OWL_NS.unionOf) | |
1500 @Callable | |
1501 def getUnions(): | |
1502 pass | |
1503 getUnions = Callable(getUnions) | |
1504 | |
1505 def __init__(self, identifier=None, operator=OWL_NS.intersectionOf, | |
1506 members=None, graph=None): | |
1507 if operator is None: | |
1508 props = [] | |
1509 for s, p, o in graph.triples_choices((identifier, | |
1510 [OWL_NS.intersectionOf, | |
1511 OWL_NS.unionOf], | |
1512 None)): | |
1513 props.append(p) | |
1514 operator = p | |
1515 assert len(props) == 1, repr(props) | |
1516 Class.__init__(self, identifier, graph=graph) | |
1517 assert operator in [OWL_NS.intersectionOf, | |
1518 OWL_NS.unionOf], str(operator) | |
1519 self._operator = operator | |
1520 rdfList = list( | |
1521 self.graph.objects(predicate=operator, subject=self.identifier)) | |
1522 assert not members or not rdfList, \ | |
1523 "This is a previous boolean class description!" + \ | |
1524 repr(Collection(self.graph, rdfList[0]).n3()) | |
1525 OWLRDFListProxy.__init__(self, rdfList, members) | |
1526 | |
1527 def copy(self): | |
1528 """ | |
1529 Create a copy of this class | |
1530 """ | |
1531 copyOfClass = BooleanClass( | |
1532 operator=self._operator, members=list(self), graph=self.graph) | |
1533 return copyOfClass | |
1534 | |
1535 def serialize(self, graph): | |
1536 clonedList = Collection(graph, BNode()) | |
1537 for cl in self._rdfList: | |
1538 clonedList.append(cl) | |
1539 CastClass(cl, self.graph).serialize(graph) | |
1540 | |
1541 graph.add((self.identifier, self._operator, clonedList.uri)) | |
1542 | |
1543 for s, p, o in self.graph.triples((self.identifier, None, None)): | |
1544 if p != self._operator: | |
1545 graph.add((s, p, o)) | |
1546 self._serialize(graph) | |
1547 | |
1548 def isPrimitive(self): | |
1549 return False | |
1550 | |
1551 def changeOperator(self, newOperator): | |
1552 """ | |
1553 Converts a unionOf / intersectionOf class expression into one | |
1554 that instead uses the given operator | |
1555 | |
1556 | |
1557 >>> testGraph = Graph() | |
1558 >>> Individual.factoryGraph = testGraph | |
1559 >>> EX = Namespace("http://example.com/") | |
1560 >>> namespace_manager = NamespaceManager(Graph()) | |
1561 >>> namespace_manager.bind('ex', EX, override=False) | |
1562 >>> testGraph.namespace_manager = namespace_manager | |
1563 >>> fire = Class(EX.Fire) | |
1564 >>> water = Class(EX.Water) | |
1565 >>> testClass = BooleanClass(members=[fire,water]) | |
1566 >>> testClass #doctest: +SKIP | |
1567 ( ex:Fire AND ex:Water ) | |
1568 >>> testClass.changeOperator(OWL_NS.unionOf) | |
1569 >>> testClass #doctest: +SKIP | |
1570 ( ex:Fire OR ex:Water ) | |
1571 >>> try: testClass.changeOperator(OWL_NS.unionOf) | |
1572 ... except Exception%s: print(e) | |
1573 The new operator is already being used! | |
1574 | |
1575 """ % 'as e' if PY3 else ', e' | |
1576 assert newOperator != self._operator, \ | |
1577 "The new operator is already being used!" | |
1578 self.graph.remove((self.identifier, self._operator, self._rdfList.uri)) | |
1579 self.graph.add((self.identifier, newOperator, self._rdfList.uri)) | |
1580 self._operator = newOperator | |
1581 | |
1582 def __repr__(self): | |
1583 """ | |
1584 Returns the Manchester Syntax equivalent for this class | |
1585 """ | |
1586 return manchesterSyntax( | |
1587 self._rdfList.uri, self.graph, boolean=self._operator) | |
1588 | |
1589 def __or__(self, other): | |
1590 """ | |
1591 Adds other to the list and returns self | |
1592 """ | |
1593 assert self._operator == OWL_NS.unionOf | |
1594 self._rdfList.append(classOrIdentifier(other)) | |
1595 return self | |
1596 | |
1597 | |
1598 def AllDifferent(members): | |
1599 """ | |
1600 DisjointClasses(' description description { description } ')' | |
1601 | |
1602 """ | |
1603 pass | |
1604 | |
1605 | |
1606 class Restriction(Class): | |
1607 """ | |
1608 restriction ::= 'restriction(' | |
1609 datavaluedPropertyID dataRestrictionComponent | |
1610 { dataRestrictionComponent } ')' | |
1611 | 'restriction(' individualvaluedPropertyID | |
1612 individualRestrictionComponent | |
1613 { individualRestrictionComponent } ')' | |
1614 """ | |
1615 | |
1616 restrictionKinds = [OWL_NS.allValuesFrom, | |
1617 OWL_NS.someValuesFrom, | |
1618 OWL_NS.hasValue, | |
1619 OWL_NS.maxCardinality, | |
1620 OWL_NS.minCardinality] | |
1621 | |
1622 def __init__(self, | |
1623 onProperty, | |
1624 graph=Graph(), | |
1625 allValuesFrom=None, | |
1626 someValuesFrom=None, | |
1627 value=None, | |
1628 cardinality=None, | |
1629 maxCardinality=None, | |
1630 minCardinality=None, | |
1631 identifier=None): | |
1632 super(Restriction, self).__init__(identifier, | |
1633 graph=graph, | |
1634 skipOWLClassMembership=True) | |
1635 if (self.identifier, | |
1636 OWL_NS.onProperty, | |
1637 propertyOrIdentifier(onProperty)) not in graph: | |
1638 graph.add((self.identifier, OWL_NS.onProperty, | |
1639 propertyOrIdentifier(onProperty))) | |
1640 self.onProperty = onProperty | |
1641 restrTypes = [ | |
1642 (allValuesFrom, OWL_NS.allValuesFrom), | |
1643 (someValuesFrom, OWL_NS.someValuesFrom), | |
1644 (value, OWL_NS.hasValue), | |
1645 (cardinality, OWL_NS.cardinality), | |
1646 (maxCardinality, OWL_NS.maxCardinality), | |
1647 (minCardinality, OWL_NS.minCardinality)] | |
1648 validRestrProps = [(i, oTerm) for (i, oTerm) in restrTypes if i] | |
1649 assert len(validRestrProps) | |
1650 restrictionRange, restrictionType = validRestrProps.pop() | |
1651 self.restrictionType = restrictionType | |
1652 if isinstance(restrictionRange, Identifier): | |
1653 self.restrictionRange = restrictionRange | |
1654 elif isinstance(restrictionRange, Class): | |
1655 self.restrictionRange = classOrIdentifier(restrictionRange) | |
1656 else: | |
1657 self.restrictionRange = first(self.graph.objects(self.identifier, | |
1658 restrictionType)) | |
1659 if (self.identifier, | |
1660 restrictionType, | |
1661 self.restrictionRange) not in self.graph: | |
1662 self.graph.add( | |
1663 (self.identifier, restrictionType, self.restrictionRange)) | |
1664 assert self.restrictionRange is not None, Class(self.identifier) | |
1665 if (self.identifier, RDF.type, OWL_NS.Restriction) not in self.graph: | |
1666 self.graph.add((self.identifier, RDF.type, OWL_NS.Restriction)) | |
1667 self.graph.remove((self.identifier, RDF.type, OWL_NS.Class)) | |
1668 | |
1669 def serialize(self, graph): | |
1670 """ | |
1671 >>> g1 = Graph() | |
1672 >>> g2 = Graph() | |
1673 >>> EX = Namespace("http://example.com/") | |
1674 >>> namespace_manager = NamespaceManager(g1) | |
1675 >>> namespace_manager.bind('ex', EX, override=False) | |
1676 >>> namespace_manager = NamespaceManager(g2) | |
1677 >>> namespace_manager.bind('ex', EX, override=False) | |
1678 >>> Individual.factoryGraph = g1 | |
1679 >>> prop = Property(EX.someProp, baseType=OWL_NS.DatatypeProperty) | |
1680 >>> restr1 = (Property( | |
1681 ... EX.someProp, | |
1682 ... baseType=OWL_NS.DatatypeProperty)) | some | (Class(EX.Foo)) | |
1683 >>> restr1 #doctest: +SKIP | |
1684 ( ex:someProp SOME ex:Foo ) | |
1685 >>> restr1.serialize(g2) | |
1686 >>> Individual.factoryGraph = g2 | |
1687 >>> list(Property( | |
1688 ... EX.someProp,baseType=None).type | |
1689 ... ) #doctest: +NORMALIZE_WHITESPACE +SKIP | |
1690 [rdflib.term.URIRef( | |
1691 u'http://www.w3.org/2002/07/owl#DatatypeProperty')] | |
1692 """ | |
1693 Property( | |
1694 self.onProperty, graph=self.graph, baseType=None).serialize(graph) | |
1695 for s, p, o in self.graph.triples((self.identifier, None, None)): | |
1696 graph.add((s, p, o)) | |
1697 if p in [OWL_NS.allValuesFrom, OWL_NS.someValuesFrom]: | |
1698 CastClass(o, self.graph).serialize(graph) | |
1699 | |
1700 def isPrimitive(self): | |
1701 return False | |
1702 | |
1703 def __hash__(self): | |
1704 return hash((self.onProperty, self.restrictionRange)) | |
1705 | |
1706 def __eq__(self, other): | |
1707 """ | |
1708 Equivalence of restrictions is determined by equivalence of the | |
1709 property in question and the restriction 'range' | |
1710 """ | |
1711 assert isinstance(other, Class), repr(other) + repr(type(other)) | |
1712 if isinstance(other, Restriction): | |
1713 return other.onProperty == self.onProperty and \ | |
1714 other.restrictionRange == self.restrictionRange | |
1715 else: | |
1716 return False | |
1717 | |
1718 def _get_onProperty(self): | |
1719 return list(self.graph.objects( | |
1720 subject=self.identifier, predicate=OWL_NS.onProperty))[0] | |
1721 | |
1722 def _set_onProperty(self, prop): | |
1723 triple = ( | |
1724 self.identifier, OWL_NS.onProperty, propertyOrIdentifier(prop)) | |
1725 if not prop: | |
1726 return | |
1727 elif triple in self.graph: | |
1728 return | |
1729 else: | |
1730 self.graph.set(triple) | |
1731 | |
1732 @TermDeletionHelper(OWL_NS.onProperty) | |
1733 def _del_onProperty(self): | |
1734 pass | |
1735 | |
1736 onProperty = property(_get_onProperty, _set_onProperty, _del_onProperty) | |
1737 | |
1738 def _get_allValuesFrom(self): | |
1739 for i in self.graph.objects( | |
1740 subject=self.identifier, predicate=OWL_NS.allValuesFrom): | |
1741 return Class(i, graph=self.graph) | |
1742 return None | |
1743 | |
1744 def _set_allValuesFrom(self, other): | |
1745 triple = ( | |
1746 self.identifier, OWL_NS.allValuesFrom, classOrIdentifier(other)) | |
1747 if not other: | |
1748 return | |
1749 elif triple in self.graph: | |
1750 return | |
1751 else: | |
1752 self.graph.set(triple) | |
1753 | |
1754 @TermDeletionHelper(OWL_NS.allValuesFrom) | |
1755 def _del_allValuesFrom(self): | |
1756 pass | |
1757 | |
1758 allValuesFrom = property( | |
1759 _get_allValuesFrom, _set_allValuesFrom, _del_allValuesFrom) | |
1760 | |
1761 def _get_someValuesFrom(self): | |
1762 for i in self.graph.objects( | |
1763 subject=self.identifier, predicate=OWL_NS.someValuesFrom): | |
1764 return Class(i, graph=self.graph) | |
1765 return None | |
1766 | |
1767 def _set_someValuesFrom(self, other): | |
1768 triple = ( | |
1769 self.identifier, OWL_NS.someValuesFrom, classOrIdentifier(other)) | |
1770 if not other: | |
1771 return | |
1772 elif triple in self.graph: | |
1773 return | |
1774 else: | |
1775 self.graph.set(triple) | |
1776 | |
1777 @TermDeletionHelper(OWL_NS.someValuesFrom) | |
1778 def _del_someValuesFrom(self): | |
1779 pass | |
1780 | |
1781 someValuesFrom = property( | |
1782 _get_someValuesFrom, _set_someValuesFrom, _del_someValuesFrom) | |
1783 | |
1784 def _get_hasValue(self): | |
1785 for i in self.graph.objects( | |
1786 subject=self.identifier, predicate=OWL_NS.hasValue): | |
1787 return Class(i, graph=self.graph) | |
1788 return None | |
1789 | |
1790 def _set_hasValue(self, other): | |
1791 triple = (self.identifier, OWL_NS.hasValue, classOrIdentifier(other)) | |
1792 if not other: | |
1793 return | |
1794 elif triple in self.graph: | |
1795 return | |
1796 else: | |
1797 self.graph.set(triple) | |
1798 | |
1799 @TermDeletionHelper(OWL_NS.hasValue) | |
1800 def _del_hasValue(self): | |
1801 pass | |
1802 | |
1803 hasValue = property(_get_hasValue, _set_hasValue, _del_hasValue) | |
1804 | |
1805 def _get_cardinality(self): | |
1806 for i in self.graph.objects( | |
1807 subject=self.identifier, predicate=OWL_NS.cardinality): | |
1808 return Class(i, graph=self.graph) | |
1809 return None | |
1810 | |
1811 def _set_cardinality(self, other): | |
1812 triple = ( | |
1813 self.identifier, OWL_NS.cardinality, classOrIdentifier(other)) | |
1814 if not other: | |
1815 return | |
1816 elif triple in self.graph: | |
1817 return | |
1818 else: | |
1819 self.graph.set(triple) | |
1820 | |
1821 @TermDeletionHelper(OWL_NS.cardinality) | |
1822 def _del_cardinality(self): | |
1823 pass | |
1824 | |
1825 cardinality = property( | |
1826 _get_cardinality, _set_cardinality, _del_cardinality) | |
1827 | |
1828 def _get_maxCardinality(self): | |
1829 for i in self.graph.objects( | |
1830 subject=self.identifier, predicate=OWL_NS.maxCardinality): | |
1831 return Class(i, graph=self.graph) | |
1832 return None | |
1833 | |
1834 def _set_maxCardinality(self, other): | |
1835 triple = ( | |
1836 self.identifier, OWL_NS.maxCardinality, classOrIdentifier(other)) | |
1837 if not other: | |
1838 return | |
1839 elif triple in self.graph: | |
1840 return | |
1841 else: | |
1842 self.graph.set(triple) | |
1843 | |
1844 @TermDeletionHelper(OWL_NS.maxCardinality) | |
1845 def _del_maxCardinality(self): | |
1846 pass | |
1847 | |
1848 maxCardinality = property( | |
1849 _get_maxCardinality, _set_maxCardinality, _del_maxCardinality) | |
1850 | |
1851 def _get_minCardinality(self): | |
1852 for i in self.graph.objects( | |
1853 subject=self.identifier, predicate=OWL_NS.minCardinality): | |
1854 return Class(i, graph=self.graph) | |
1855 return None | |
1856 | |
1857 def _set_minCardinality(self, other): | |
1858 triple = ( | |
1859 self.identifier, OWL_NS.minCardinality, classOrIdentifier(other)) | |
1860 if not other: | |
1861 return | |
1862 elif triple in self.graph: | |
1863 return | |
1864 else: | |
1865 self.graph.set(triple) | |
1866 | |
1867 @TermDeletionHelper(OWL_NS.minCardinality) | |
1868 def _del_minCardinality(self): | |
1869 pass | |
1870 | |
1871 minCardinality = property( | |
1872 _get_minCardinality, _set_minCardinality, _del_minCardinality) | |
1873 | |
1874 def restrictionKind(self): | |
1875 for p in self.graph.triple_choices((self.identifier, | |
1876 self.restrictionKinds, | |
1877 None)): | |
1878 return p.split(OWL_NS)[-1] | |
1879 raise | |
1880 | |
1881 def __repr__(self): | |
1882 """ | |
1883 Returns the Manchester Syntax equivalent for this restriction | |
1884 """ | |
1885 return manchesterSyntax(self.identifier, self.graph) | |
1886 | |
1887 ### Infix Operators ### | |
1888 | |
1889 | |
1890 some = Infix(lambda prop, _class: Restriction(prop, graph=_class.graph, | |
1891 someValuesFrom=_class)) | |
1892 only = Infix(lambda prop, _class: Restriction(prop, graph=_class.graph, | |
1893 allValuesFrom=_class)) | |
1894 max = Infix(lambda prop, _class: Restriction(prop, graph=prop.graph, | |
1895 maxCardinality=_class)) | |
1896 min = Infix(lambda prop, _class: Restriction(prop, graph=prop.graph, | |
1897 minCardinality=_class)) | |
1898 exactly = Infix(lambda prop, _class: Restriction(prop, graph=prop.graph, | |
1899 cardinality=_class)) | |
1900 value = Infix( | |
1901 lambda prop, _class: Restriction(prop, graph=prop.graph, value=_class)) | |
1902 | |
1903 PropertyAbstractSyntax =\ | |
1904 """ | |
1905 %s( %s { %s } | |
1906 %s | |
1907 { 'super(' datavaluedPropertyID ')'} ['Functional'] | |
1908 { domain( %s ) } { range( %s ) } )""" | |
1909 | |
1910 | |
1911 class Property(AnnotatableTerms): | |
1912 """ | |
1913 axiom ::= 'DatatypeProperty(' datavaluedPropertyID ['Deprecated'] | |
1914 { annotation } | |
1915 { 'super(' datavaluedPropertyID ')'} ['Functional'] | |
1916 { 'domain(' description ')' } { 'range(' dataRange ')' } ')' | |
1917 | 'ObjectProperty(' individualvaluedPropertyID ['Deprecated'] | |
1918 { annotation } | |
1919 { 'super(' individualvaluedPropertyID ')' } | |
1920 [ 'inverseOf(' individualvaluedPropertyID ')' ] [ 'Symmetric' ] | |
1921 [ 'Functional' | 'InverseFunctional' | | |
1922 'Functional' 'InverseFunctional' | | |
1923 'Transitive' ] | |
1924 { 'domain(' description ')' } { 'range(' description ')' } ') | |
1925 """ | |
1926 | |
1927 def setupVerbAnnotations(self, verbAnnotations): | |
1928 if isinstance(verbAnnotations, tuple): | |
1929 TV_sgProp, TV_plProp, TV_vbg = verbAnnotations | |
1930 else: | |
1931 TV_sgProp = verbAnnotations | |
1932 TV_plProp = verbAnnotations | |
1933 TV_vbg = verbAnnotations | |
1934 if TV_sgProp: | |
1935 self.TV_sgProp.extent = [(self.identifier, | |
1936 self.handleAnnotation(TV_sgProp))] | |
1937 if TV_plProp: | |
1938 self.TV_plProp.extent = [(self.identifier, | |
1939 self.handleAnnotation(TV_plProp))] | |
1940 if TV_vbg: | |
1941 self.TV_vbgProp.extent = [(self.identifier, | |
1942 self.handleAnnotation(TV_vbg))] | |
1943 | |
1944 def __init__( | |
1945 self, identifier=None, graph=None, baseType=OWL_NS.ObjectProperty, | |
1946 subPropertyOf=None, domain=None, range=None, inverseOf=None, | |
1947 otherType=None, equivalentProperty=None, | |
1948 comment=None, | |
1949 verbAnnotations=None, | |
1950 nameAnnotation=None, | |
1951 nameIsLabel=False): | |
1952 super(Property, self).__init__(identifier, graph, | |
1953 nameAnnotation, nameIsLabel) | |
1954 if verbAnnotations: | |
1955 self.setupVerbAnnotations(verbAnnotations) | |
1956 | |
1957 assert not isinstance(self.identifier, BNode) | |
1958 if baseType is None: | |
1959 # None give, determine via introspection | |
1960 self._baseType = first( | |
1961 Individual(self.identifier, graph=self.graph).type) | |
1962 else: | |
1963 if (self.identifier, RDF.type, baseType) not in self.graph: | |
1964 self.graph.add((self.identifier, RDF.type, baseType)) | |
1965 self._baseType = baseType | |
1966 self.subPropertyOf = subPropertyOf | |
1967 self.inverseOf = inverseOf | |
1968 self.domain = domain | |
1969 self.range = range | |
1970 self.comment = comment and comment or [] | |
1971 | |
1972 def serialize(self, graph): | |
1973 for fact in self.graph.triples((self.identifier, None, None)): | |
1974 graph.add(fact) | |
1975 for p in itertools.chain(self.subPropertyOf, | |
1976 self.inverseOf): | |
1977 p.serialize(graph) | |
1978 for c in itertools.chain(self.domain, | |
1979 self.range): | |
1980 CastClass(c, self.graph).serialize(graph) | |
1981 | |
1982 def _get_extent(self, graph=None): | |
1983 for triple in (graph is None and self.graph or graph).triples( | |
1984 (None, self.identifier, None)): | |
1985 yield triple | |
1986 | |
1987 def _set_extent(self, other): | |
1988 if not other: | |
1989 return | |
1990 for subj, obj in other: | |
1991 self.graph.add((subj, self.identifier, obj)) | |
1992 | |
1993 extent = property(_get_extent, _set_extent) | |
1994 | |
1995 def __repr__(self): | |
1996 rt = [] | |
1997 if OWL_NS.ObjectProperty in self.type: | |
1998 rt.append('ObjectProperty( %s annotation(%s)' | |
1999 % (self.qname, first(self.comment) and | |
2000 first(self.comment) or '')) | |
2001 if first(self.inverseOf): | |
2002 twoLinkInverse = first(first(self.inverseOf).inverseOf) | |
2003 if twoLinkInverse \ | |
2004 and twoLinkInverse.identifier == self.identifier: | |
2005 inverseRepr = first(self.inverseOf).qname | |
2006 else: | |
2007 inverseRepr = repr(first(self.inverseOf)) | |
2008 rt.append(" inverseOf( %s )%s" % ( | |
2009 inverseRepr, | |
2010 OWL_NS.SymmetricProperty in self.type and | |
2011 ' Symmetric' or | |
2012 '')) | |
2013 for s, p, roleType in self.graph.triples_choices( | |
2014 (self.identifier, | |
2015 RDF.type, | |
2016 [OWL_NS.FunctionalProperty, | |
2017 OWL_NS.InverseFunctionalProperty, | |
2018 OWL_NS.TransitiveProperty])): | |
2019 rt.append(str(roleType.split(OWL_NS)[-1])) | |
2020 else: | |
2021 rt.append('DatatypeProperty( %s %s' | |
2022 % (self.qname, first(self.comment) and | |
2023 first(self.comment) or | |
2024 '')) | |
2025 for s, p, roleType in self.graph.triples(( | |
2026 self.identifier, RDF.type, OWL_NS.FunctionalProperty)): | |
2027 rt.append(' Functional') | |
2028 | |
2029 def canonicalName(term, g): | |
2030 normalizedName = classOrIdentifier(term) | |
2031 if isinstance(normalizedName, BNode): | |
2032 return term | |
2033 elif normalizedName.startswith(_XSD_NS): | |
2034 return str(term) | |
2035 elif first(g.triples_choices(( | |
2036 normalizedName, | |
2037 [OWL_NS.unionOf, | |
2038 OWL_NS.intersectionOf], None))): | |
2039 return repr(term) | |
2040 else: | |
2041 return str(term.qname) | |
2042 rt.append(' '.join([" super( %s )" % canonicalName( | |
2043 superP, self.graph) | |
2044 for superP in self.subPropertyOf])) | |
2045 rt.append(' '.join([" domain( %s )" % canonicalName( | |
2046 domain, self.graph) | |
2047 for domain in self.domain])) | |
2048 rt.append(' '.join([" range( %s )" % canonicalName( | |
2049 range, self.graph) | |
2050 for range in self.range])) | |
2051 rt = '\n'.join([expr for expr in rt if expr]) | |
2052 rt += '\n)' | |
2053 return str(rt).encode('utf-8') | |
2054 | |
2055 def _get_subPropertyOf(self): | |
2056 for anc in self.graph.objects( | |
2057 subject=self.identifier, predicate=RDFS.subPropertyOf): | |
2058 yield Property(anc, graph=self.graph, baseType=None) | |
2059 | |
2060 def _set_subPropertyOf(self, other): | |
2061 if not other: | |
2062 return | |
2063 for sP in other: | |
2064 self.graph.add( | |
2065 (self.identifier, RDFS.subPropertyOf, classOrIdentifier(sP))) | |
2066 | |
2067 @TermDeletionHelper(RDFS.subPropertyOf) | |
2068 def _del_subPropertyOf(self): | |
2069 pass | |
2070 | |
2071 subPropertyOf = property( | |
2072 _get_subPropertyOf, _set_subPropertyOf, _del_subPropertyOf) | |
2073 | |
2074 def _get_inverseOf(self): | |
2075 for anc in self.graph.objects( | |
2076 subject=self.identifier, predicate=OWL_NS.inverseOf): | |
2077 yield Property(anc, graph=self.graph, baseType=None) | |
2078 | |
2079 def _set_inverseOf(self, other): | |
2080 if not other: | |
2081 return | |
2082 self.graph.add( | |
2083 (self.identifier, OWL_NS.inverseOf, classOrIdentifier(other))) | |
2084 | |
2085 @TermDeletionHelper(OWL_NS.inverseOf) | |
2086 def _del_inverseOf(self): | |
2087 pass | |
2088 | |
2089 inverseOf = property(_get_inverseOf, _set_inverseOf, _del_inverseOf) | |
2090 | |
2091 def _get_domain(self): | |
2092 for dom in self.graph.objects( | |
2093 subject=self.identifier, predicate=RDFS.domain): | |
2094 yield Class(dom, graph=self.graph) | |
2095 | |
2096 def _set_domain(self, other): | |
2097 if not other: | |
2098 return | |
2099 if isinstance(other, (Individual, Identifier)): | |
2100 self.graph.add( | |
2101 (self.identifier, RDFS.domain, classOrIdentifier(other))) | |
2102 else: | |
2103 for dom in other: | |
2104 self.graph.add( | |
2105 (self.identifier, RDFS.domain, classOrIdentifier(dom))) | |
2106 | |
2107 @TermDeletionHelper(RDFS.domain) | |
2108 def _del_domain(self): | |
2109 pass | |
2110 | |
2111 domain = property(_get_domain, _set_domain, _del_domain) | |
2112 | |
2113 def _get_range(self): | |
2114 for ran in self.graph.objects( | |
2115 subject=self.identifier, predicate=RDFS.range): | |
2116 yield Class(ran, graph=self.graph) | |
2117 | |
2118 def _set_range(self, ranges): | |
2119 if not ranges: | |
2120 return | |
2121 if isinstance(ranges, (Individual, Identifier)): | |
2122 self.graph.add( | |
2123 (self.identifier, RDFS.range, classOrIdentifier(ranges))) | |
2124 else: | |
2125 for range in ranges: | |
2126 self.graph.add( | |
2127 (self.identifier, RDFS.range, classOrIdentifier(range))) | |
2128 | |
2129 @TermDeletionHelper(RDFS.range) | |
2130 def _del_range(self): | |
2131 pass | |
2132 | |
2133 range = property(_get_range, _set_range, _del_range) | |
2134 | |
2135 def replace(self, other): | |
2136 # extension = [] | |
2137 for s, p, o in self.extent: | |
2138 self.graph.add((s, propertyOrIdentifier(other), o)) | |
2139 self.graph.remove((None, self.identifier, None)) | |
2140 | |
2141 | |
2142 def CommonNSBindings(graph, additionalNS={}): | |
2143 """ | |
2144 Takes a graph and binds the common namespaces (rdf,rdfs, & owl) | |
2145 """ | |
2146 namespace_manager = NamespaceManager(graph) | |
2147 namespace_manager.bind('rdfs', RDFS) | |
2148 namespace_manager.bind('rdf', RDF) | |
2149 namespace_manager.bind('owl', OWL_NS) | |
2150 for prefix, uri in list(additionalNS.items()): | |
2151 namespace_manager.bind(prefix, uri, override=False) | |
2152 graph.namespace_manager = namespace_manager | |
2153 | |
2154 | |
2155 def test(): | |
2156 import doctest | |
2157 doctest.testmod() | |
2158 | |
2159 | |
2160 if __name__ == '__main__': | |
2161 test() |