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()