1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package org.openrdf.elmo.dynabean.helpers;
30
31 import info.aduna.iteration.CloseableIteration;
32
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Set;
38
39 import org.openrdf.elmo.exceptions.ElmoCompositionException;
40 import org.openrdf.model.Literal;
41 import org.openrdf.model.Resource;
42 import org.openrdf.model.Statement;
43 import org.openrdf.model.URI;
44 import org.openrdf.model.Value;
45 import org.openrdf.model.vocabulary.OWL;
46 import org.openrdf.model.vocabulary.RDF;
47 import org.openrdf.model.vocabulary.RDFS;
48 import org.openrdf.query.BindingSet;
49 import org.openrdf.query.MalformedQueryException;
50 import org.openrdf.query.QueryEvaluationException;
51 import org.openrdf.query.QueryLanguage;
52 import org.openrdf.query.TupleQuery;
53 import org.openrdf.query.TupleQueryResult;
54 import org.openrdf.repository.RepositoryException;
55 import org.openrdf.repository.contextaware.ContextAwareConnection;
56
57
58
59
60
61
62
63 public class RdfsClassInterpreter {
64
65 private ContextAwareConnection conn;
66
67 public RdfsClassInterpreter(ContextAwareConnection conn) {
68 this.conn = conn;
69 }
70
71 public void interpetRdfClass(Collection<URI> types,
72 OntologyDigester digester) throws RepositoryException,
73 QueryEvaluationException {
74 Collection<URI> rdfTypes = types;
75 rdfTypes = includeSubclasses(rdfTypes);
76 digestDeclaredProperties(rdfTypes, digester);
77 for (Resource restriction : getRestrictions(rdfTypes)) {
78 digestRestrictionProperties(restriction, digester);
79 }
80 cleanup(digester);
81 }
82
83 private void digestDeclaredProperties(Collection<URI> rdfTypes,
84 OntologyDigester digester) throws RepositoryException,
85 QueryEvaluationException {
86 TupleQueryResult result = null;
87 StringBuilder query = null;
88 try {
89 for (URI rdfType : rdfTypes) {
90 if (query == null) {
91 query = new StringBuilder();
92 query.append("SELECT p FROM {p} rdfs:domain {c}");
93 query.append(" WHERE c = <");
94 query.append(rdfType);
95 query.append(">");
96 } else {
97 query.append(" OR c = <");
98 query.append(rdfType);
99 query.append(">");
100 }
101 }
102 assert query != null;
103 TupleQuery preparedQuery = conn.prepareTupleQuery(
104 QueryLanguage.SERQL, query.toString());
105 result = preparedQuery.evaluate();
106 while (result.hasNext()) {
107 BindingSet sol = result.next();
108 URI pred = (URI) sol.getValue("p");
109 digester.addPredicate(pred);
110 CloseableIteration<? extends Statement, RepositoryException> iter2 = null;
111 try {
112 iter2 = conn.getStatements(pred, RDFS.RANGE, null, true);
113 while (iter2.hasNext()) {
114 Value val = iter2.next().getObject();
115 assert val instanceof URI : val;
116 digester.addRdfType(pred, (URI) val);
117 }
118 } finally {
119 if (iter2 != null)
120 iter2.close();
121 }
122
123 if (conn.hasStatement(pred, RDF.TYPE, OWL.FUNCTIONALPROPERTY,
124 true))
125 digester.setFunctional(pred, true);
126 }
127 } catch (MalformedQueryException e) {
128 throw new ElmoCompositionException(e);
129 } finally {
130 if (result != null)
131 result.close();
132 }
133 }
134
135 private Iterable<Resource> getRestrictions(Collection<URI> rdfTypes)
136 throws RepositoryException, QueryEvaluationException {
137 Set<Resource> classes = new HashSet<Resource>();
138 TupleQueryResult result = null;
139 try {
140 StringBuilder query = null;
141 for (URI rdfType : rdfTypes) {
142 if (query == null) {
143 query = new StringBuilder();
144 query
145 .append("SELECT r FROM {c} rdfs:subClassOf {r} rdf:type {<");
146 query.append(OWL.RESTRICTION);
147 query.append(">}");
148 query.append(" WHERE c = <");
149 query.append(rdfType);
150 query.append(">");
151 } else {
152 query.append(" OR c = <");
153 query.append(rdfType);
154 query.append(">");
155 }
156 }
157 assert query != null;
158 TupleQuery preparedQuery = conn.prepareTupleQuery(
159 QueryLanguage.SERQL, query.toString());
160 result = preparedQuery.evaluate();
161 while (result.hasNext()) {
162 BindingSet sol = result.next();
163 classes.add((Resource) sol.getValue("r"));
164 }
165 } catch (MalformedQueryException e) {
166 throw new ElmoCompositionException(e);
167 } finally {
168 if (result != null)
169 result.close();
170 }
171 return classes;
172 }
173
174 private void digestRestrictionProperties(Resource restriction,
175 OntologyDigester digester) throws RepositoryException {
176 URI pred = (URI) getFirstValue(restriction, OWL.ONPROPERTY);
177 if (pred == null)
178 return;
179 digester.addPredicate(pred);
180 CloseableIteration<? extends Statement, RepositoryException> iter = null;
181 try {
182 iter = conn.getStatements(restriction, OWL.ALLVALUESFROM, null,
183 true);
184 while (iter.hasNext()) {
185 Value val = iter.next().getObject();
186 assert val instanceof URI;
187 digester.addRdfType(pred, (URI) val);
188 }
189 } finally {
190 if (iter != null)
191 iter.close();
192 }
193 int cardinality = getFirstInt(restriction, OWL.CARDINALITY);
194 if (cardinality == 1)
195 digester.setFunctional(pred, true);
196 cardinality = getFirstInt(restriction, OWL.MAXCARDINALITY);
197 if (cardinality == 1)
198 digester.setFunctional(pred, true);
199 }
200
201 private void cleanup(OntologyDigester digester) throws RepositoryException {
202 for (URI pred : digester.getPredicates()) {
203 List<URI> rdfTypes = digester.getRdfTypes(pred);
204 if (rdfTypes == null)
205 continue;
206 rdfTypes = filterOutSuperclasses(rdfTypes);
207 digester.setRdfTypes(pred, rdfTypes);
208 }
209 digester.end();
210 }
211
212 private List<URI> filterOutSuperclasses(List<URI> types)
213 throws RepositoryException {
214 if (types.size() < 2)
215 return types;
216 ArrayList<URI> list = new ArrayList<URI>(types.size());
217 for (int i = 0, n = types.size(); i < n; i++) {
218 URI c = types.get(i);
219 boolean isSubClass = false;
220 for (int j = 0, m = types.size(); j < m; j++) {
221 if (i == j)
222 continue;
223 URI d = types.get(j);
224 if (c.equals(d)) {
225 isSubClass = true;
226 break;
227 }
228 boolean subclass = conn.hasStatement(d, RDFS.SUBCLASSOF, c,
229 true);
230 if (subclass) {
231 isSubClass = true;
232 break;
233 }
234 }
235 if (!isSubClass)
236 list.add(c);
237 }
238 return list;
239 }
240
241 private Collection<URI> includeSubclasses(Collection<URI> rdfTypes)
242 throws RepositoryException {
243 Set<URI> classes = new HashSet<URI>();
244 for (URI rdfType : rdfTypes) {
245 includeSubclasses(rdfType, classes);
246 }
247 return classes;
248 }
249
250 private Collection<URI> includeSubclasses(URI rdfType, Set<URI> result)
251 throws RepositoryException {
252 CloseableIteration<? extends Statement, RepositoryException> iter = null;
253 try {
254 result.add(rdfType);
255 iter = conn.getStatements(rdfType, RDFS.SUBCLASSOF, null, true);
256 while (iter.hasNext()) {
257 Value uri = iter.next().getObject();
258 if (uri instanceof URI && !result.contains(uri)) {
259 includeSubclasses((URI) uri, result);
260 }
261 }
262 } finally {
263 if (iter != null)
264 iter.close();
265 }
266 return result;
267 }
268
269 private Value getFirstValue(Resource subj, URI pred)
270 throws RepositoryException {
271 CloseableIteration<? extends Statement, RepositoryException> iter = null;
272 try {
273 iter = conn.getStatements(subj, pred, null, false);
274 if (iter.hasNext())
275 return iter.next().getObject();
276 return null;
277 } finally {
278 if (iter != null)
279 iter.close();
280 }
281 }
282
283 private int getFirstInt(Resource subj, URI pred) throws RepositoryException {
284 Literal lit = (Literal)getFirstValue(subj, pred);
285 if (lit == null)
286 return 0;
287 return Integer.parseInt(lit.getLabel());
288 }
289 }