1 from unittest import TestCase
3 from rdflib import ConjunctiveGraph, BNode, Literal, Namespace, URIRef
4 from rdflib.plugins.sparql import prepareQuery
6 from htsworkflow.util.rdfhelp import \
7 add_default_schemas, load_string_into_model, dump_model
8 from htsworkflow.util.rdfns import *
9 from htsworkflow.util.rdfinfer import Infer
11 from rdflib.namespace import FOAF
13 MINI_FOAF_ONTOLOGY = """
14 @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
15 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
16 @prefix owl: <http://www.w3.org/2002/07/owl#> .
17 @prefix foaf: <http://xmlns.com/foaf/0.1/> .
21 a rdfs:Class, owl:Class ;
22 rdfs:comment "An agent (person, group, software or physical artifiact)."@en;
26 a rdfs:Class, owl:Class, foaf:Agent ;
30 a rdf:Property, owl:DatatypeProperty, owl:FunctionalProperty ;
31 rdfs:comment "The age in years of some agent." ;
32 rdfs:domain foaf:Agent ;
34 rdfs:range rdfs:Literal .
37 a rdf:Property, owl:DatatypeProperty ;
38 rdfs:comment "Family name of some person." ;
39 rdfs:label "familyName" ;
40 rdfs:domain foaf:Person ;
41 rdfs:range rdfs:Literal .
44 a rdf:Property, owl:DatatypeProperty ;
45 rdfs:comment "the first name of a person." ;
46 rdfs:domain foaf:Person ;
47 rdfs:label "firstname" ;
48 rdfs:range rdfs:Literal .
51 a rdfs:Class, owl:Class ;
52 rdfs:comment "A document." .
55 a rdfs:Class, owl:Class ;
56 rdfs:comment "An image." ;
57 rdfs:subClassOf foaf:Document .
60 a rdf:Property, owl:ObjectProperty ;
61 rdfs:comment "A thing depicted in this representation." ;
62 rdfs:domain foaf:Image ;
63 rdfs:range owl:Thing ;
64 owl:inverseOf foaf:depiction .
67 a rdf:Property, owl:ObjectProperty ;
68 rdfs:comment "Depiction of some thing." ;
69 rdfs:domain owl:Thing ;
70 rdfs:range foaf:Image ;
71 owl:inverseOf foaf:depicts .
75 @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
76 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
77 @prefix owl: <http://www.w3.org/2002/07/owl#> .
78 @prefix foaf: <http://xmlns.com/foaf/0.1/> .
81 foaf:firstName "Diane" ;
82 foaf:familyName "Trout" ;
83 a foaf:Person, owl:Thing ;
84 <http://example.org/other_literal> "value" ;
85 <http://example.org/other_resource> <http://example.org/resource> .
87 <http://example.org/me.jpg>
88 a foaf:Image, owl:Thing ;
92 class TestInfer(TestCase):
94 self.model = ConjunctiveGraph()
95 add_default_schemas(self.model)
96 self.model.parse(data=MINI_FOAF_ONTOLOGY, format='turtle')
99 fooNS = Namespace('http://example.org/')
100 self.model.parse(data=FOAF_DATA, format='turtle')
101 inference = Infer(self.model)
103 s = [fooNS['me.jpg'], RDF['type'], RDFS['Class']]
104 found = list(self.model.triples(s))
105 self.assertEqual(len(found), 0)
106 inference._rule_class()
107 s = [fooNS['me.jpg'], RDF['type'], RDFS['Class']]
108 found = list(self.model.triples(s))
109 self.assertEqual(len(found), 1)
111 def test_inverse_of(self):
112 fooNS = Namespace('http://example.org/')
113 self.model.parse(data=FOAF_DATA, format='turtle')
114 inference = Infer(self.model)
115 depiction = (None, FOAF['depiction'], fooNS['me.jpg'])
116 size = len(self.model)
117 found_statements = list(self.model.triples(depiction))
118 self.assertEqual(len(found_statements), 0)
119 inference._rule_inverse_of()
120 found_statements = list(self.model.triples(depiction))
121 self.assertEqual(len(found_statements), 1)
123 # we should've added one statement.
124 self.assertEqual(len(self.model), size + 1)
126 size = len(self.model)
127 inference._rule_inverse_of()
128 # we should already have both versions in our model
129 self.assertEqual(len(self.model), size)
131 def test_validate_types(self):
132 fooNS = Namespace('http://example.org/')
133 self.model.parse(data=FOAF_DATA, format='turtle')
134 inference = Infer(self.model)
136 errors = list(inference._validate_types())
137 self.assertEqual(len(errors), 0)
139 s = (fooNS['document'], DC['title'], Literal("bleem"))
141 errors = list(inference._validate_types())
142 self.assertEqual(len(errors), 1)
144 def test_validate_undefined_properties_in_schemas(self):
145 fooNS = Namespace('http://example.org/')
146 inference = Infer(self.model)
148 errors = list(inference._validate_undefined_properties())
149 self.assertEqual(len(errors), 0)
151 def test_validate_undefined_properties_in_inference(self):
152 fooNS = Namespace('http://example.org/')
153 foafNS = Namespace('http://xmlns.com/foaf/0.1/')
155 self.model.parse(data=FOAF_DATA, format='turtle')
157 inference = Infer(self.model)
158 errors = list(inference._validate_undefined_properties())
159 self.assertEqual(len(errors), 2)
161 inference = Infer(self.model)
162 errors = list(inference._validate_property_types())
163 self.assertEqual(len(errors), 0)
165 s = (fooNS['me.jpg'], FOAF['firstName'], Literal("name"))
167 errors = list(inference._validate_property_types())
168 self.assertEqual(len(errors), 1)
169 startswith = 'Domain of '
170 self.assertEqual(errors[0][:len(startswith)], startswith)
171 self.assertTrue('http://example.org/me.jpg' in errors[0])
172 endswith = 'http://xmlns.com/foaf/0.1/Person'
173 self.assertEqual(errors[0][-len(endswith):], endswith)
176 errors = list(inference._validate_property_types())
177 self.assertEqual(len(errors), 0)
178 s = (fooNS['foo.txt'], RDF['type'], FOAF['Document'])
180 s = (fooNS['me.jpg'], FOAF['depicts'], FOAF['foo.txt'])
183 errors = list(inference._validate_property_types())
184 self.assertEqual(len(errors), 1)
185 startswith = 'Range of '
186 self.assertEqual(errors[0][:len(startswith)], startswith)
187 self.assertTrue('http://example.org/me.jpg' in errors[0])
188 endswith = 'http://www.w3.org/2002/07/owl#Thing'
189 self.assertEqual(errors[0][-len(endswith):], endswith)
192 def test_property_multiple_domain_types(self):
193 """Can we process a property with multiple domain types?
196 @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
197 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
198 @prefix foo: <http://example.org/> .
199 @prefix bar: <http://example.com/> .
201 foo:AClass a rdfs:Class .
202 foo:BClass a rdfs:Class .
203 bar:ABarClass a rdfs:Class .
205 foo:aprop a rdf:Property ;
206 rdfs:domain foo:AClass ;
207 rdfs:domain bar:ABarClass ;
208 rdfs:range foo:BClass .
210 foo:object a foo:BClass .
211 foo:subject a foo:AClass ;
212 foo:aprop foo:object .
213 bar:subject a bar:ABarClass ;
214 foo:aprop foo:object .
216 self.model.parse(data=turtle, format='turtle')
217 inference = Infer(self.model)
219 errmsg = list(inference._validate_property_types())
220 self.failUnlessEqual(len(errmsg), 0)
224 from unittest import TestSuite, defaultTestLoader
226 suite.addTests(defaultTestLoader.loadTestsFromTestCase(TestInfer))
230 if __name__ == "__main__":
231 from unittest import main
232 main(defaultTest="suite")