aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/rsacomb/RDFoxClassExprConverter.scala
blob: 227c25b1b31fddf69fcf3e50cd1d8c2f62ba59b9 (plain) (blame)
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package rsacomb

import scala.collection.JavaConverters._
import java.util.stream.{Stream,Collectors}

import org.semanticweb.owlapi.model.{OWLClassExpression, OWLClass, OWLObjectSomeValuesFrom, OWLObjectIntersectionOf, OWLObjectOneOf, OWLObjectMaxCardinality}
import org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx
import tech.oxfordsemantic.jrdfox.logic.{BindAtom, BuiltinFunctionCall, TupleTableName}
import tech.oxfordsemantic.jrdfox.logic.{Atom, Term, Variable, Literal, Datatype}

import rsacomb.SkolemStrategy
import rsacomb.RDFoxRuleShards
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression
import org.semanticweb.owlapi.model.OWLObjectProperty

object RDFoxClassExprConverter {

  def apply(
    term : Term = Variable.create("x"),
    skolem : SkolemStrategy = SkolemStrategy.None,
    unsafe : List[OWLObjectPropertyExpression] = List()
  ) : RDFoxClassExprConverter =
	  new RDFoxClassExprConverter(term, skolem, unsafe)

  def merge(rules : List[RDFoxRuleShards]) : RDFoxRuleShards = {
    rules.foldLeft(RDFoxRuleShards(List(),List())) {
      (r1,r2) =>
        RDFoxRuleShards(
          r1.res ++ r2.res,
          r1.ext ++ r2.ext
        )
    }
  }

} // object RDFoxClassExprConverter

class RDFoxClassExprConverter(term : Term, skolem : SkolemStrategy, unsafe : List[OWLObjectPropertyExpression])
  extends OWLClassExpressionVisitorEx[RDFoxRuleShards]
{

  // OWLClass
  override
  def visit(expr : OWLClass) : RDFoxRuleShards = {
    val name = expr.getIRI.getIRIString
    val atom = List(Atom.create(TupleTableName.create(name), term))
    RDFoxRuleShards(atom,List())
  }

  // OWLObjectIntersectionOf
  override
  def visit(expr : OWLObjectIntersectionOf) : RDFoxRuleShards = {
    val visitor = new RDFoxClassExprConverter(term, skolem, unsafe)
    // TODO: maybe using `flatMap` instead of `merge` + `map` works as well
	RDFoxClassExprConverter.merge (
      expr.asConjunctSet.asScala.toList
          .map((e : OWLClassExpression) => e.accept(visitor))
    )
  }

  // OWLObjectOneOf
  override
  def visit(expr : OWLObjectOneOf) : RDFoxRuleShards = {
    val visitor = RDFoxClassExprConverter(term,skolem)
    // TODO: review nominal handling. Here we are taking "just" one
    val ind = expr.individuals.collect(Collectors.toList()).asScala
                  .filter(_.isOWLNamedIndividual)
                  .head // restricts to proper "nominals"
                  .asOWLNamedIndividual.getIRI.getIRIString
    val atom = List(Atom.create(
      TupleTableName.create("owl:sameAs"), term, Literal.create(ind, Datatype.IRI_REFERENCE)
    ))
    RDFoxRuleShards(atom,List())
  }

  // OWLObjectSomeValuesFrom
  override
  def visit(expr : OWLObjectSomeValuesFrom) : RDFoxRuleShards = {
    // TODO: variables needs to be handled at visitor level. Hardcoding
    // the name of the varibles might lead to errors for complex cases.
    val y = Variable.create("y")
    val prop = expr.getProperty()
    // Computes the result of rule skolemization. Depending on the used 
    // technique it might involve the introduction of additional atoms,
    // and/or fresh constants and variables.
    val (head, body, term1) = skolem match {
        case SkolemStrategy.None => (List(), List(), y)
        case SkolemStrategy.Constant(c) => (List(), List(), Literal.create(c, Datatype.IRI_REFERENCE))
        case SkolemStrategy.ConstantRSA(c) => {
          val lit = Literal.create(c, Datatype.IRI_REFERENCE)
          if (unsafe.contains(prop))
            (List(Atom.create(TupleTableName.create("internal:PE"),term,lit), Atom.create(TupleTableName.create("internal:U"),lit)), List(), lit)
          else 
            (List(), List(), lit)
        }
        case SkolemStrategy.Standard(f) => 
          // At the time of writing the RDFox library does not have a
          // particular class for the "SKOLEM" operator and it is instead
          // a simple builtin function with a "special" name.
          (List(),List(BindAtom.create(BuiltinFunctionCall.create("SKOLEM",term),y)),y)
    }
    val classVisitor = new RDFoxClassExprConverter(term1, skolem, unsafe)
    val classResult = expr.getFiller.accept(classVisitor)
    val propertyVisitor = new RDFoxPropertyExprConverter(term, term1, skolem)
    val propertyResult = expr.getProperty.accept(propertyVisitor)
    RDFoxRuleShards(
      classResult.res ++ propertyResult ++ head,
      classResult.ext ++ body
    )
  }

  // OWLObjectMaxCardinality
  override
  def visit(expr : OWLObjectMaxCardinality) : RDFoxRuleShards = {
    // TODO: again, no hardcoded variables
    val vars = List(Variable.create("y"),Variable.create("z"))
    val classResult = RDFoxClassExprConverter.merge(
      vars.map(new RDFoxClassExprConverter(_,skolem, unsafe))
          .map(expr.getFiller.accept(_))
    )
    val propertyResult = 
      vars.map(new RDFoxPropertyExprConverter(term,_,skolem))
          .map(expr.getProperty.accept(_))
          .flatten
    RDFoxRuleShards(
      List(Atom.create(TupleTableName.create("owl:sameAs"),vars(0),vars(1))),
      classResult.res ++ propertyResult
    )
  }
	
  def doDefault(expr : OWLClassExpression) : RDFoxRuleShards =
    RDFoxRuleShards(List(),List())

} // class RDFoxClassExprConverter