Viewing file: RdfsHandler.py (23.39 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
######################################################################## # $Header: /var/local/cvsroot/4Suite/Ft/Rdf/RdfsHandler.py,v 1.9 2005/03/04 15:03:04 mbrown Exp $ """ An RDF schema validator for statements in a Model
Copyright 2005 Fourthought, Inc. (USA). Detailed license and copyright information: http://4suite.org/COPYRIGHT Project home, documentation, distributions: http://4suite.org/ """
# Obtained from http://www.w3.org/TR/rdf-schema/rdfs-namespace # on 2005-03-03. French labels and xml:lang attrs added locally. # owl:Ontology Class definition added locally, derived from # http://www.w3.org/2002/07/owl, so that the schema itself will validate
RDFS_XML = """<?xml version="1.0" encoding="utf-8"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<owl:Ontology rdf:about="http://www.w3.org/2000/01/rdf-schema#" dc:title="The RDF Schema vocabulary (RDFS)"/>
<rdfs:Class rdf:about="http://www.w3.org/2002/07/owl#Ontology"> <rdfs:label>Ontology</rdfs:label> </rdfs:Class>
<rdfs:Class rdf:about="http://www.w3.org/2000/01/rdf-schema#Resource"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">Resource</rdfs:label> <rdfs:label xml:lang="fr">Ressource</rdfs:label> <rdfs:comment>The class resource, everything.</rdfs:comment> </rdfs:Class>
<rdf:Property rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#type"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">type</rdfs:label> <rdfs:label xml:lang="fr">type</rdfs:label> <rdfs:comment>The subject is an instance of a class.</rdfs:comment> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Class"/> <rdfs:domain rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdf:Property>
<rdfs:Class rdf:about="http://www.w3.org/2000/01/rdf-schema#Class"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">Class</rdfs:label> <rdfs:label xml:lang="fr">Classe</rdfs:label> <rdfs:comment>The class of classes.</rdfs:comment> <rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdfs:Class>
<rdf:Property rdf:about="http://www.w3.org/2000/01/rdf-schema#subClassOf"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">subClassOf</rdfs:label> <rdfs:label xml:lang="fr">sousClasseDe</rdfs:label> <rdfs:comment>The subject is a subclass of a class.</rdfs:comment> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Class"/> <rdfs:domain rdf:resource="http://www.w3.org/2000/01/rdf-schema#Class"/> </rdf:Property>
<rdf:Property rdf:about="http://www.w3.org/2000/01/rdf-schema#subPropertyOf"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">subPropertyOf</rdfs:label> <rdfs:label xml:lang="fr">sousPropriétéDe</rdfs:label> <rdfs:comment>The subject is a subproperty of a property.</rdfs:comment> <rdfs:range rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/> <rdfs:domain rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/> </rdf:Property>
<rdfs:Class rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">Property</rdfs:label> <rdfs:label xml:lang="fr">Propriété</rdfs:label> <rdfs:comment>The class of RDF properties.</rdfs:comment> <rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdfs:Class>
<rdf:Property rdf:about="http://www.w3.org/2000/01/rdf-schema#comment"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">comment</rdfs:label> <rdfs:label xml:lang="fr">commentaire</rdfs:label> <rdfs:comment>A description of the subject resource.</rdfs:comment> <rdfs:domain rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> </rdf:Property>
<rdf:Property rdf:about="http://www.w3.org/2000/01/rdf-schema#label"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">label</rdfs:label> <rdfs:label xml:lang="fr">libellé</rdfs:label> <rdfs:comment>A human-readable name for the subject.</rdfs:comment> <rdfs:domain rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> </rdf:Property>
<!-- was: rdfs:ConstraintProperty rdf:ID="domain" --> <rdf:Property rdf:about="http://www.w3.org/2000/01/rdf-schema#domain"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">domain</rdfs:label> <rdfs:label xml:lang="fr">domaine</rdfs:label> <rdfs:comment>A domain of the subject property.</rdfs:comment> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Class"/> <rdfs:domain rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/> </rdf:Property>
<!-- was: rdfs:ConstraintProperty rdf:ID="range" --> <rdf:Property rdf:about="http://www.w3.org/2000/01/rdf-schema#range"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">range</rdfs:label> <rdfs:label xml:lang="fr">étendue</rdfs:label> <rdfs:comment>A range of the subject property.</rdfs:comment> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Class"/> <rdfs:domain rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/> </rdf:Property>
<rdf:Property rdf:about="http://www.w3.org/2000/01/rdf-schema#seeAlso"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">seeAlso</rdfs:label> <rdfs:label xml:lang="fr">voirAussi</rdfs:label> <rdfs:comment>Further information about the subject resource.</rdfs:comment> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> <rdfs:domain rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdf:Property>
<rdf:Property rdf:about="http://www.w3.org/2000/01/rdf-schema#isDefinedBy"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:subPropertyOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#seeAlso"/> <rdfs:label xml:lang="en">isDefinedBy</rdfs:label> <rdfs:label xml:lang="fr">estDéfiniPar</rdfs:label> <rdfs:comment>The defininition of the subject resource.</rdfs:comment> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> <rdfs:domain rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdf:Property>
<rdfs:Class rdf:about="http://www.w3.org/2000/01/rdf-schema#Literal"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">Literal</rdfs:label> <rdfs:label xml:lang="fr">Littéral</rdfs:label> <rdfs:comment>The class of literal values, eg. textual strings and integers.</rdfs:comment> <rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdfs:Class>
<rdfs:Class rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">Statement</rdfs:label> <rdfs:label xml:lang="fr">Déclaration</rdfs:label> <rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> <rdfs:comment>The class of RDF statements.</rdfs:comment> </rdfs:Class>
<rdf:Property rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#subject"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">subject</rdfs:label> <rdfs:label xml:lang="fr">sujet</rdfs:label> <rdfs:comment>The subject of the subject RDF statement.</rdfs:comment> <rdfs:domain rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement"/> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdf:Property>
<rdf:Property rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">predicate</rdfs:label> <rdfs:label xml:lang="fr">prédicat</rdfs:label> <rdfs:comment>The predicate of the subject RDF statement.</rdfs:comment> <rdfs:domain rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement"/> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdf:Property>
<rdf:Property rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#object"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">object</rdfs:label> <rdfs:label xml:lang="fr">objet</rdfs:label> <rdfs:comment>The object of the subject RDF statement.</rdfs:comment> <rdfs:domain rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement"/> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdf:Property>
<rdfs:Class rdf:about="http://www.w3.org/2000/01/rdf-schema#Container"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">Container</rdfs:label> <rdfs:label xml:lang="fr">Enveloppe</rdfs:label> <rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> <rdfs:comment>The class of RDF containers.</rdfs:comment> </rdfs:Class>
<rdfs:Class rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">Bag</rdfs:label> <rdfs:label xml:lang="fr">Ensemble</rdfs:label> <rdfs:comment>The class of unordered containers.</rdfs:comment> <rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Container"/> </rdfs:Class>
<rdfs:Class rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">Sequence</rdfs:label> <rdfs:label xml:lang="fr">Séquence</rdfs:label> <rdfs:comment>The class of ordered containers.</rdfs:comment> <rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Container"/> </rdfs:Class>
<rdfs:Class rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">Alt</rdfs:label> <rdfs:label xml:lang="fr">Choix</rdfs:label> <rdfs:comment>The class of containers of alternatives.</rdfs:comment> <rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Container"/> </rdfs:Class>
<rdfs:Class rdf:about="http://www.w3.org/2000/01/rdf-schema#ContainerMembershipProperty"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">ContainerMembershipProperty</rdfs:label> <rdfs:comment>The class of container membership properties, rdf:_1, rdf:_2, ..., all of which are sub-properties of 'member'.</rdfs:comment> <rdfs:subClassOf rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/> </rdfs:Class>
<rdf:Property rdf:about="http://www.w3.org/2000/01/rdf-schema#member"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">member</rdfs:label> <rdfs:comment>A member of the subject resource.</rdfs:comment> <rdfs:domain rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdf:Property>
<rdf:Property rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#value"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">value</rdfs:label> <rdfs:label xml:lang="fr">valuer</rdfs:label> <rdfs:comment>Idiomatic property used for structured values.</rdfs:comment> <rdfs:domain rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdf:Property>
<!-- the following are new additions, Nov 2002 -->
<rdfs:Class rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#List"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">List</rdfs:label> <rdfs:comment>The class of RDF Lists.</rdfs:comment> <rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/></rdfs:Class>
<rdf:List rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">nil</rdfs:label> <rdfs:comment>The empty list, with no items in it. If the rest of a list is nil then the list has no more items in it.</rdfs:comment> </rdf:List>
<rdf:Property rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#first"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">first</rdfs:label> <rdfs:comment>The first item in the subject RDF list.</rdfs:comment> <rdfs:domain rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#List"/> <rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/> </rdf:Property>
<rdf:Property rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">rest</rdfs:label> <rdfs:comment>The rest of the subject RDF list after the first item.</rdfs:comment> <rdfs:domain rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#List"/> <rdfs:range rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#List"/> </rdf:Property>
<rdfs:Class rdf:about="http://www.w3.org/2000/01/rdf-schema#Datatype"> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/2000/01/rdf-schema#"/> <rdfs:label xml:lang="en">Datatype</rdfs:label> <rdfs:comment>The class of RDF datatypes.</rdfs:comment> <rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Class"/> </rdfs:Class>
<rdfs:Datatype rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral"> <rdfs:subClassOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/> <rdfs:isDefinedBy rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/> <rdfs:label xml:lang="en">XMLLiteral</rdfs:label> <rdfs:comment>The class of XML literal values.</rdfs:comment> </rdfs:Datatype>
<rdf:Description rdf:about="http://www.w3.org/2000/01/rdf-schema#"> <rdfs:seeAlso rdf:resource="http://www.w3.org/2000/01/rdf-schema-more"/> </rdf:Description>
</rdf:RDF>"""
from Ft import FtException from Ft.Lib.Uri import OsPathToUri from Ft.Rdf import Model, SchemaHandler, RdfException from Ft.Rdf import RDF_MS_BASE, RDF_SCHEMA_BASE from Ft.Rdf.Serializers.Dom import Serializer
class RdfsConstraintViolation(FtException): PROPERTY_HAS_MULTIPLE_RANGES = 1 INVALID_DOMAIN_FOR_PROPERTY = 2 INVALID_RANGE_FOR_PROPERTY = 3
def __init__(self, errorCode, *args): import MessageSource FtException.__init__(self, errorCode, MessageSource.RDFS_ERROR_MESSAGES, args)
class RdfsHandler(SchemaHandler): """ Processing of RDF schema information on behalf of a model instance. Note that a RdfsHandler is designed to be associated with a single model in its lifecycle, which is basically: init -> initModel -> <user's schema operations> -> reclaim Do not attempt to reuse a RdfsHandler with multiple models unless you really know what you're doing """
def __init__(self): """Initializer for a RdfsHandler. There are no parameters.""" from Ft.Rdf.Drivers import Memory db = Memory.CreateDb('') self._coreRdfsModel = Model.Model(db, None) from Ft.Xml.Domlette import NonvalidatingReader self._reader = NonvalidatingReader self._serializer = Serializer() self._model = None self._active = False self._deserialized_URIs = {} return
def _deserialize(self, model, isrc, scope=None): """ Given a model, InputSource, and optional scope, deserializes the RDF/XML document wrapped by the InputSource into the model. Caches InputSource URIs so as not to deserialize the same document twice. """ uri = isrc.uri if uri not in self._deserialized_URIs: doc = self._reader.parse(isrc) self._serializer.deserialize(model, doc, scope) self._deserialized_URIs[uri] = True return
def initModel(self, model): """ Make sure that the core schema statements are in the model """ self._model = model SchemaHandler.initModel(self) #FIXME: Use faster init method than deserialization dummy_uri = OsPathToUri(__file__, attemptAbsolute=True) dummy_uri += '-INTERNAL-RDFS-XML-STRING' from Ft.Xml.InputSource import DefaultFactory isrc = DefaultFactory.fromString(RDFS_XML, dummy_uri) self._deserialize(self._model, isrc, scope=RDF_SCHEMA_BASE) #Keep around a copy for future reference isrc = DefaultFactory.fromString(RDFS_XML, dummy_uri) self._deserialize(self._coreRdfsModel, isrc, scope=RDF_SCHEMA_BASE) self._active = True return
def _complete(self, subject, predicate, object, statementUri, scope, flags): if self._active and predicate: #FIXME: Deal with statementUri more smartly #Gather all sub-properties for equivalence in the complete sub_prop_flags = {} remain_flags = flags.copy() if flags.get("predicateFlags"): sub_prop_flags = {'subjectFlags': flags.get("predicateFlags")} del remain_flags["predicateFlags"] props = [] new_props = self._model._complete( None, RDF_SCHEMA_BASE + 'subPropertyOf', predicate, statementUri, scope, sub_prop_flags ) props.extend(new_props) while new_props: newer_props = [] for prop in new_props: newer_props.extend(self._model._complete( None, RDF_SCHEMA_BASE + 'subPropertyOf', prop.subject, statementUri, scope, {})) new_props = newer_props props.extend(new_props) matches = self._model._complete( subject, predicate, object, statementUri, scope, flags ) for prop in props: matches.extend(self._model._complete( subject, prop.subject, object, statementUri, scope, remain_flags)) return matches else: return self._model._complete(subject, predicate, object, statementUri, scope, flags)
def isCoreRdfs(self, stmt): """Checks whether a statement comes from the core RDF meta-model.""" return self._coreRdfsModel.contains(stmt)
def isInstance(self, obj, class_): """Checks whether a resource is an instance of a class. Note that this is also true if the resource is an instance of any subclass of the given class.""" class_stmts = self._model.complete(obj, RDF_MS_BASE + 'type', None) for cs in class_stmts: if self.isSubClass(cs.object, class_): return True return False
def isSubClass(self, class1, class2): """Checks whether a class is an instance of another class."""
#Recursive for now. Is it worth moving to iteration? if class1 == class2: return True subclass_stmts = self._model.complete(class1, RDF_SCHEMA_BASE + 'subClassOf', None) if not subclass_stmts: return False if subclass_stmts[0].object == class2: return True return self.isSubClass(subclass_stmts[0].object, class2)
def processNewStatements(self, newStmts): """Called by the Mode when a new statement is about to be added.""" if self._active and newStmts: self.checkConstraints(newStmts) for stmt in newStmts: self._active = False if stmt.predicate == RDF_SCHEMA_BASE + 'isDefinedBy': from Ft.Xml.InputSource import DefaultFactory isrc = DefaultFactory.fromUri(stmt.object) self._deserialize(self._model, isrc) self._active = True return
def checkConstraints(self, newStmts): """ Raises exception if constraint violation found, else returns normally Does not yet check Extended Constraints (provide hooks?) """ domain_uri = RDF_SCHEMA_BASE + 'domain' range_uri = RDF_SCHEMA_BASE + 'range' property_uri = RDF_MS_BASE + 'Property' resource_uri = RDF_SCHEMA_BASE + 'Resource' literal_uri = RDF_SCHEMA_BASE + 'Literal' seen_domains = {} seen_ranges = {} for newStmt in newStmts: #First check whether the statement itself #is the introduction of a constraint predicate = newStmt.predicate if self.isSubClass(newStmt.subject, RDF_MS_BASE + 'Property'): if predicate in (domain_uri, range_uri): continue #Now check whether the statement is governed by another constraint if self.isInstance(predicate, property_uri): if predicate not in seen_domains: domains = self._model.complete(predicate, domain_uri, None) seen_domains[predicate] = domains else: domains = seen_domains[predicate] if predicate not in seen_ranges: ranges = self._model.complete(predicate, range_uri, None) if len(ranges) > 1: raise RdfsConstraintViolation(RdfsConstraintViolation.PROPERTY_HAS_MULTIPLE_RANGES, predicate) seen_ranges[predicate] = ranges else: ranges = seen_ranges[predicate] if domains: meets_constraints = False for domain in domains: if domain.object == resource_uri: meets_constraints = True if self.isInstance(newStmt.subject, domain.object): meets_constraints = True if not meets_constraints: raise RdfsConstraintViolation(RdfsConstraintViolation.INVALID_DOMAIN_FOR_PROPERTY, str(newStmt.subject), str(predicate)) if ranges: if not self.isInstance(newStmt.object, ranges[0].object) and ranges[0].object not in (resource_uri, literal_uri): raise RdfsConstraintViolation(RdfsConstraintViolation.INVALID_RANGE_FOR_PROPERTY, str(newStmt.object), str(newStmt.predicate)) return
|