b40f46151f2d45c1243318fdd79d7720fcb3ee07
[htsworkflow.git] / htsworkflow / util / test / test_rdfinfer.py
1 from unittest2 import TestCase
2
3 import RDF
4
5 from htsworkflow.util.rdfhelp import get_model, \
6      add_default_schemas, add_schema, load_string_into_model, dump_model
7 from htsworkflow.util.rdfns import *
8 from htsworkflow.util.rdfinfer import Infer
9
10 foafNS = RDF.NS('http://xmlns.com/foaf/0.1/')
11
12 MINI_FOAF_ONTOLOGY = """
13 @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
14 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
15 @prefix owl: <http://www.w3.org/2002/07/owl#> .
16 @prefix foaf: <http://xmlns.com/foaf/0.1/> .
17
18
19 foaf:Agent
20      a rdfs:Class, owl:Class ;
21      rdfs:comment "An agent (person, group, software or physical artifiact)."@en;
22      rdfs:label "Agent" .
23
24 foaf:Person
25      a rdfs:Class, owl:Class, foaf:Agent ;
26      rdfs:label "Person" .
27
28 foaf:age
29      a rdf:Property, owl:DatatypeProperty, owl:FunctionalProperty ;
30      rdfs:comment "The age in years of some agent." ;
31      rdfs:domain foaf:Agent ;
32      rdfs:label "age";
33      rdfs:range rdfs:Literal .
34
35 foaf:familyName
36      a rdf:Property, owl:DatatypeProperty ;
37      rdfs:comment "Family name of some person." ;
38      rdfs:label "familyName" ;
39      rdfs:domain foaf:Person ;
40      rdfs:range rdfs:Literal .
41
42 foaf:firstName
43      a rdf:Property, owl:DatatypeProperty ;
44      rdfs:comment "the first name of a person." ;
45      rdfs:domain foaf:Person ;
46      rdfs:label "firstname" ;
47      rdfs:range rdfs:Literal .
48
49 foaf:Document
50      a rdfs:Class, owl:Class ;
51      rdfs:comment "A document." .
52
53 foaf:Image
54      a rdfs:Class, owl:Class ;
55      rdfs:comment "An image." ;
56      rdfs:subClassOf foaf:Document .
57
58 foaf:depicts
59      a rdf:Property, owl:ObjectProperty ;
60      rdfs:comment "A thing depicted in this representation." ;
61      rdfs:domain foaf:Image ;
62      rdfs:range owl:Thing ;
63      owl:inverseOf foaf:depiction .
64
65 foaf:depiction
66      a rdf:Property, owl:ObjectProperty ;
67      rdfs:comment "Depiction of some thing." ;
68      rdfs:domain owl:Thing ;
69      rdfs:range foaf:Image ;
70      owl:inverseOf foaf:depicts .
71 """
72
73 FOAF_DATA = """
74 @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
75 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
76 @prefix owl: <http://www.w3.org/2002/07/owl#> .
77 @prefix foaf: <http://xmlns.com/foaf/0.1/> .
78
79 _:me
80      foaf:firstName "Diane" ;
81      foaf:familyName "Trout" ;
82      a foaf:Person, owl:Thing ;
83      <http://example.org/other_literal> "value" ;
84      <http://example.org/other_resource> <http://example.org/resource> .
85
86 <http://example.org/me.jpg>
87      a foaf:Image, owl:Thing ;
88      foaf:depicts _:me .
89 """
90
91 class TestInfer(TestCase):
92     def setUp(self):
93         self.model = get_model()
94         add_default_schemas(self.model)
95         load_string_into_model(self.model, 'turtle', MINI_FOAF_ONTOLOGY)
96
97     def test_class(self):
98         fooNS = RDF.NS('http://example.org/')
99         load_string_into_model(self.model, 'turtle', FOAF_DATA)
100         inference = Infer(self.model)
101
102         s = RDF.Statement(fooNS['me.jpg'], rdfNS['type'], rdfsNS['Class'])
103         found = list(self.model.find_statements(s))
104         self.assertEqual(len(found), 0)
105         inference._rule_class()
106         s = RDF.Statement(fooNS['me.jpg'], rdfNS['type'], rdfsNS['Class'])
107         found = list(self.model.find_statements(s))
108         self.assertEqual(len(found), 1)
109
110     def test_inverse_of(self):
111         fooNS = RDF.NS('http://example.org/')
112         load_string_into_model(self.model, 'turtle', FOAF_DATA)
113         inference = Infer(self.model)
114         depiction = RDF.Statement(None,
115                                   foafNS['depiction'],
116                                   fooNS['me.jpg'])
117         size = self.model.size()
118         found_statements = list(self.model.find_statements(depiction))
119         self.assertEqual(len(found_statements), 0)
120         inference._rule_inverse_of()
121         found_statements = list(self.model.find_statements(depiction))
122         self.assertEqual(len(found_statements), 1)
123
124         # we should've added one statement.
125         self.assertEqual(self.model.size(), size + 1)
126
127         size = self.model.size()
128         inference._rule_inverse_of()
129         # we should already have both versions in our model
130         self.assertEqual(self.model.size(), size)
131
132     def test_validate_types(self):
133         fooNS = RDF.NS('http://example.org/')
134         load_string_into_model(self.model, 'turtle', FOAF_DATA)
135         inference = Infer(self.model)
136
137         errors = list(inference._validate_types())
138         self.assertEqual(len(errors), 0)
139
140         s = RDF.Statement(fooNS['document'],
141                           dcNS['title'],
142                           RDF.Node("bleem"))
143         self.model.append(s)
144         errors = list(inference._validate_types())
145         self.assertEqual(len(errors), 1)
146
147     def test_validate_undefined_properties(self):
148         fooNS = RDF.NS('http://example.org/')
149         inference = Infer(self.model)
150
151         errors = list(inference._validate_undefined_properties())
152         self.assertEqual(len(errors), 0)
153
154         load_string_into_model(self.model, 'turtle', FOAF_DATA)
155
156         errors = list(inference._validate_undefined_properties())
157         self.assertEqual(len(errors), 2)
158
159
160     def test_validate_undefined_properties(self):
161         fooNS = RDF.NS('http://example.org/')
162         foafNS = RDF.NS('http://xmlns.com/foaf/0.1/')
163         load_string_into_model(self.model, 'turtle', FOAF_DATA)
164         inference = Infer(self.model)
165
166         errors = list(inference._validate_property_types())
167         self.assertEqual(len(errors), 0)
168
169         s = RDF.Statement(fooNS['me.jpg'],
170                           foafNS['firstName'],
171                           RDF.Node("name"))
172         self.model.append(s)
173         errors = list(inference._validate_property_types())
174         self.assertEqual(len(errors), 1)
175         startswith = 'Domain of '
176         self.assertEqual(errors[0][:len(startswith)], startswith)
177         self.assertTrue('http://example.org/me.jpg' in errors[0])
178         endswith = 'http://xmlns.com/foaf/0.1/Person'
179         self.assertEqual(errors[0][-len(endswith):], endswith)
180         del self.model[s]
181
182         errors = list(inference._validate_property_types())
183         self.assertEqual(len(errors), 0)
184         s = RDF.Statement(fooNS['foo.txt'], rdfNS['type'], foafNS['Document'])
185         self.model.append(s)
186         s = RDF.Statement(fooNS['me.jpg'],
187                           foafNS['depicts'],
188                           foafNS['foo.txt'])
189         self.model.append(s)
190
191         errors = list(inference._validate_property_types())
192         self.assertEqual(len(errors), 1)
193         startswith = 'Range of '
194         self.assertEqual(errors[0][:len(startswith)], startswith)
195         self.assertTrue('http://example.org/me.jpg' in errors[0])
196         endswith = 'http://www.w3.org/2002/07/owl#Thing'
197         self.assertEqual(errors[0][-len(endswith):], endswith)
198         del self.model[s]
199
200     def test_property_multiple_domain_types(self):
201         """Can we process a property with multiple domain types?
202         """
203         turtle = """
204         @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
205         @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
206         @prefix foo: <http://example.org/> .
207         @prefix bar: <http://example.com/> .
208
209         foo:AClass a rdfs:Class .
210         foo:BClass a rdfs:Class .
211         bar:ABarClass a rdfs:Class .
212
213         foo:aprop a rdf:Property ;
214             rdfs:domain foo:AClass ;
215             rdfs:domain bar:ABarClass ;
216             rdfs:range foo:BClass .
217
218         foo:object a foo:BClass .
219         foo:subject a foo:AClass ;
220            foo:aprop foo:object .
221         bar:subject a bar:ABarClass ;
222            foo:aprop foo:object .
223         """
224         load_string_into_model(self.model, 'turtle', turtle)
225         inference = Infer(self.model)
226
227         errmsg = list(inference._validate_property_types())
228         print errmsg
229         self.failUnlessEqual(len(errmsg), 0)
230
231
232 def suite():
233     from unittest2 import TestSuite, defaultTestLoader
234     suite = TestSuite()
235     suite.addTests(defaultTestLoader.loadTestsFromTestCase(TestInfer))
236     return suite
237
238
239 if __name__ == "__main__":
240     from unittest2 import main
241     main(defaultTest="suite")