aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/rsacomb/RSAOntology.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/rsacomb/RSAOntology.scala')
-rw-r--r--src/main/scala/rsacomb/RSAOntology.scala165
1 files changed, 163 insertions, 2 deletions
diff --git a/src/main/scala/rsacomb/RSAOntology.scala b/src/main/scala/rsacomb/RSAOntology.scala
index 3d9210e..9d52612 100644
--- a/src/main/scala/rsacomb/RSAOntology.scala
+++ b/src/main/scala/rsacomb/RSAOntology.scala
@@ -19,6 +19,7 @@ import scalax.collection.GraphEdge.UnDiEdge
19 19
20/* Debug only */ 20/* Debug only */
21import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer 21import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer
22import tech.oxfordsemantic.jrdfox.logic._
22 23
23/* Wrapper trait for the implicit class `RSAOntology`. 24/* Wrapper trait for the implicit class `RSAOntology`.
24 */ 25 */
@@ -163,8 +164,9 @@ trait RSAOntology {
163 } yield role1 164 } yield role1
164 165
165 /* TODO: We should be able to avoid this last conversion to List. 166 /* TODO: We should be able to avoid this last conversion to List.
166 * Maybe we should just move everything to Sets instead of Lists, since 167 * Maybe we should just move everything to Sets instead of Lists,
167 * they have a more straightforward conversion from Java collections. 168 * since they have a more straightforward conversion from Java
169 * collections.
168 */ 170 */
169 (unsafe1 ++ unsafe2).toList 171 (unsafe1 ++ unsafe2).toList
170 } 172 }
@@ -184,6 +186,165 @@ trait RSAOntology {
184 Graph(edges: _*) 186 Graph(edges: _*)
185 } 187 }
186 188
189 def getFilteringProgram(query: Query): List[Rule] = {
190
191 // Import implicit conversion to RDFox IRI
192 import RDFoxUtil._
193
194 sealed trait Reified;
195 case class ReifiedHead(bind: BindAtom, atoms: List[Atom]) extends Reified
196 case class ReifiedBody(atoms: List[Atom]) extends Reified
197 case class Unaltered(formula: BodyFormula) extends Reified
198
199 def getBindAtom(atom: Atom): BindAtom = {
200 // TODO: We need to implement another way to introduce fresh
201 // variables.
202 val varA = Variable.create("A")
203 val args = atom
204 .getArguments()
205 .asScala
206 .toSeq
207 //.prepended(atom.getTupleTableName.getIRI)
208 BindAtom.create(
209 BuiltinFunctionCall
210 .create("SKOLEM", args: _*),
211 varA
212 )
213 }
214
215 def reifyAtom(atom: Atom, variable: Variable): List[Atom] = {
216 def iri(i: Int) = atom.getTupleTableName().getIRI() ++ s"_$i"
217 atom
218 .getArguments()
219 .asScala
220 .zipWithIndex
221 .map { case (t, i) => Atom.rdf(variable, iri(i), t) }
222 .toList
223 }
224
225 // Is this the best way to determine if an atom is an RDF triple?
226 // Note that we can't use `getNumberOfArguments()` because is not
227 // "consistent":
228 // - for an atom created with `rdf(<term1>, <term2>, <term3>)`,
229 // `getNumberOfArguments` returns 3
230 // - for an atom created with `Atom.create(<tupletablename>, <term1>,
231 // <term2>, <term3>)`, `getNumberOfArguments()` returns 3
232 //
233 // This is probably because `Atom.rdf(...) is implemented as:
234 // ```scala
235 // def rdf(term1: Term, term2: Term, term3: Term): Atom =
236 // Atom.create(TupleTableName.create("internal:triple"), term1, term2, term3)
237 // ```
238 def isRdfTriple(atom: Atom): Boolean =
239 atom.getTupleTableName.getIRI.equals("internal:triple")
240
241 def reify(
242 formula: BodyFormula,
243 head: Boolean
244 ): Reified = {
245 def default[A <: BodyFormula](x: A) = Unaltered(x)
246 formula match {
247 case a: Atom => {
248 if (!isRdfTriple(a)) {
249 if (head) {
250 val b = getBindAtom(a)
251 ReifiedHead(b, reifyAtom(a, b.getBoundVariable))
252 } else {
253 val varA = Variable.create("A")
254 ReifiedBody(reifyAtom(a, varA))
255 }
256 } else {
257 default(a)
258 }
259 }
260 case a => default(a)
261 }
262 }
263
264 def skolemizeRule(rule: Rule): Rule = {
265 // Rule body
266 val body =
267 rule.getBody.asScala.map(reify(_, false)).flatMap {
268 case ReifiedHead(_, _) => List(); /* handle impossible case */
269 case ReifiedBody(x) => x;
270 case Unaltered(x) => List(x)
271 }
272 // Rule head
273 val reified = rule.getHead.asScala.map(reify(_, true))
274 val skols = reified.flatMap {
275 case ReifiedHead(x, _) => Some(x);
276 case ReifiedBody(_) => None; /* handle impossible case */
277 case Unaltered(_) => None
278 }
279 val head = reified.flatMap {
280 case ReifiedHead(_, x) => x;
281 case ReifiedBody(_) => List(); /* handle impossible case */
282 case Unaltered(x) =>
283 List(x.asInstanceOf[Atom]) /* Can we do better that a cast? */
284 }
285 Rule.create(head.asJava, (skols ++ body).asJava)
286 }
287
288 def formulaToRuleBody(body: Formula): List[BodyFormula] = {
289 body match {
290 case a: BodyFormula => List(a);
291 case a: Conjunction =>
292 a.getConjuncts().asScala.toList.flatMap(formulaToRuleBody(_));
293 case _ => List() /* We don't handle this for now */
294 }
295 }
296
297 val body = formulaToRuleBody(query.getQueryFormula)
298 val vars: List[Term] = query.getAnswerVariables.asScala.toList
299 def id(t1: Term, t2: Term) =
300 Atom.create(
301 TupleTableName.create("http://127.0.0.1/ID"),
302 vars.appendedAll(List(t1, t2)).asJava
303 )
304 val qm = Atom.create(TupleTableName.create("QM"), vars.asJava)
305
306 /* Filtering program */
307 val rule1 = Rule.create(qm, body.asJava)
308 val rule3a =
309 for ((v, i) <- vars.zipWithIndex)
310 yield Rule.create(
311 id(
312 IRI.create(s"http://127.0.0.1/$i"),
313 IRI.create(s"http://127.0.0.1/$i")
314 ),
315 List(
316 qm,
317 Negation.create(
318 Atom.rdf(v, IRI.RDF_TYPE, IRI.create("http://127.0.0.1/NI"))
319 )
320 ).asJava
321 )
322 val rule3b = Rule.create(
323 id(Variable.create("V"), Variable.create("U")),
324 id(Variable.create("U"), Variable.create("V"))
325 )
326 val rule3c = Rule.create(
327 id(Variable.create("U"), Variable.create("W")),
328 List[BodyFormula](
329 id(Variable.create("U"), Variable.create("V")),
330 id(Variable.create("V"), Variable.create("W"))
331 ).asJava
332 )
333
334 var rules: List[Rule] =
335 List.empty
336 .prepended(rule3c)
337 .prepended(rule3b)
338 .prependedAll(rule3a)
339 .prepended(rule1)
340
341 // DEBUG
342 println("FILTERING PROGRAM:")
343 rules.map(skolemizeRule(_)).foreach(println(_))
344
345 List()
346 }
347
187 } // implicit class RSAOntology 348 } // implicit class RSAOntology
188 349
189} // trait RSAOntology 350} // trait RSAOntology