aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/example/RDFoxAxiomConverter.scala58
-rw-r--r--src/main/scala/example/RDFoxClassExprConverter.scala119
-rw-r--r--src/main/scala/example/RDFoxPropertyExprConverter.scala23
-rw-r--r--src/main/scala/example/RDFoxRuleShards.scala6
-rw-r--r--src/main/scala/example/RSAComb.scala138
-rw-r--r--src/main/scala/example/SkolemStrategy.scala46
-rw-r--r--src/test/scala/buzz/OWLAxiomSpec.scala302
-rw-r--r--src/test/scala/buzz/OWLClassSpec.scala259
8 files changed, 951 insertions, 0 deletions
diff --git a/src/main/scala/example/RDFoxAxiomConverter.scala b/src/main/scala/example/RDFoxAxiomConverter.scala
new file mode 100644
index 0000000..0a6272f
--- /dev/null
+++ b/src/main/scala/example/RDFoxAxiomConverter.scala
@@ -0,0 +1,58 @@
1package rsacomb
2
3import org.semanticweb.owlapi.model.{OWLAxiom, OWLSubClassOfAxiom, OWLEquivalentClassesAxiom}
4import org.semanticweb.owlapi.model.OWLAxiomVisitorEx
5
6import tech.oxfordsemantic.jrdfox.logic.Rule
7import tech.oxfordsemantic.jrdfox.logic.{Atom, Term, Literal, Individual}
8
9import scala.collection.JavaConverters._
10
11import rsacomb.SkolemStrategy
12import rsacomb.RDFoxRuleShards
13
14object RDFoxAxiomConverter {
15
16 def apply(term : Term, skolem : SkolemStrategy) : RDFoxAxiomConverter =
17 new RDFoxAxiomConverter(term, skolem)
18
19 def apply(term : Term) : RDFoxAxiomConverter =
20 new RDFoxAxiomConverter(term, SkolemStrategy.None)
21
22} // object RDFoxAxiomConverter
23
24class RDFoxAxiomConverter(term : Term, skolem : SkolemStrategy)
25 extends OWLAxiomVisitorEx[List[Rule]]
26{
27
28 override
29 def visit(axiom : OWLSubClassOfAxiom) : List[Rule] = {
30 // Skolemization is needed only for the head of an axiom
31 val subVisitor = new RDFoxClassExprConverter(term,SkolemStrategy.None)
32 val superVisitor = new RDFoxClassExprConverter(term, skolem)
33 // Each visitor returns a `RDFoxRuleShards`, a tuple (res,ext):
34 // - the `res` List is a list of atoms resulting from the conversion
35 // of the axiom.
36 // - for some Class Expressions appearing in the head of an Axiom,
37 // the conversion might produce atoms that need to appear in the
38 // body (and not in the head) of the rule. This is what the `ext`
39 // List is for.
40 val sub = axiom.getSubClass.accept(subVisitor)
41 val sup = axiom.getSuperClass.accept(superVisitor)
42 val head = sup.res.asJava
43 val body = (sub.res ++ sup.ext).asJava
44 List(Rule.create(head,body))
45 }
46
47 override
48 def visit(axiom : OWLEquivalentClassesAxiom) : List[Rule] = {
49 for {
50 axiom1 <- axiom.asPairwiseAxioms.asScala.toList
51 axiom2 <- axiom1.asOWLSubClassOfAxioms.asScala.toList
52 rule <- axiom2.accept(this)
53 } yield rule
54 }
55
56 def doDefault(axiom : OWLAxiom) : List[Rule] = List()
57
58} // class RDFoxAxiomConverter
diff --git a/src/main/scala/example/RDFoxClassExprConverter.scala b/src/main/scala/example/RDFoxClassExprConverter.scala
new file mode 100644
index 0000000..3e60461
--- /dev/null
+++ b/src/main/scala/example/RDFoxClassExprConverter.scala
@@ -0,0 +1,119 @@
1package rsacomb
2
3import scala.collection.JavaConverters._
4import java.util.stream.{Stream,Collectors}
5
6import org.semanticweb.owlapi.model.{OWLClassExpression, OWLClass, OWLObjectSomeValuesFrom, OWLObjectIntersectionOf, OWLObjectOneOf, OWLObjectMaxCardinality}
7import org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx
8import tech.oxfordsemantic.jrdfox.logic.{AtomicFormula, Bind,BuiltinFunctionCall}
9import tech.oxfordsemantic.jrdfox.logic.{Atom, Predicate, Term, Variable, Literal, Individual}
10
11import rsacomb.SkolemStrategy
12import rsacomb.RDFoxRuleShards
13
14object RDFoxClassExprConverter {
15
16 def apply(term : Term, skolem : SkolemStrategy) : RDFoxClassExprConverter =
17 new RDFoxClassExprConverter(term, skolem)
18
19 def apply(term : Term) : RDFoxClassExprConverter =
20 new RDFoxClassExprConverter(term, SkolemStrategy.None)
21
22 def merge(rules : List[RDFoxRuleShards]) : RDFoxRuleShards = {
23 rules.foldLeft(RDFoxRuleShards(List(),List())) {
24 (r1,r2) =>
25 RDFoxRuleShards(
26 r1.res ++ r2.res,
27 r1.ext ++ r2.ext
28 )
29 }
30 }
31
32} // object RDFoxClassExprConverter
33
34class RDFoxClassExprConverter(term : Term, skolem : SkolemStrategy)
35 extends OWLClassExpressionVisitorEx[RDFoxRuleShards]
36{
37
38 // OWLClass
39 override
40 def visit(expr : OWLClass) : RDFoxRuleShards = {
41 val name = expr.getIRI.getIRIString
42 val atom = List(Atom.create(Predicate.create(name), term))
43 RDFoxRuleShards(atom,List())
44 }
45
46 // OWLObjectIntersectionOf
47 override
48 def visit(expr : OWLObjectIntersectionOf) : RDFoxRuleShards = {
49 val visitor = new RDFoxClassExprConverter(term,skolem)
50 // TODO: maybe using `flatMap` instead of `merge` + `map` works as well
51 RDFoxClassExprConverter.merge (
52 expr.asConjunctSet.asScala.toList
53 .map((e : OWLClassExpression) => e.accept(visitor))
54 )
55 }
56
57 // OWLObjectOneOf
58 override
59 def visit(expr : OWLObjectOneOf) : RDFoxRuleShards = {
60 val visitor = RDFoxClassExprConverter(term,skolem)
61 // TODO: review nominal handling. Here we are taking "just" one
62 val ind = expr.individuals.collect(Collectors.toList()).asScala
63 .filter(_.isOWLNamedIndividual)
64 .head // restricts to proper "nominals"
65 .asOWLNamedIndividual.getIRI.getIRIString
66 val atom = List(Atom.create(
67 Predicate.create("owl:sameAs"), term, Individual.create(ind)
68 ))
69 RDFoxRuleShards(atom,List())
70 }
71
72 // OWLObjectSomeValuesFrom
73 override
74 def visit(expr : OWLObjectSomeValuesFrom) : RDFoxRuleShards = {
75 // TODO: variables needs to be handled at visitor level. Hardcoding
76 // the name of the varibles might lead to errors for complex cases.
77 val y = Variable.create("y")
78 val (fun,term1) = skolem match {
79 case SkolemStrategy.None => (List(),y)
80 case SkolemStrategy.Constant(c) => (List(), Individual.create(c))
81 case SkolemStrategy.Standard(f) =>
82 // At the time of writing the RDFox library does not have a
83 // particular class for the "SKOLEM" operator and it is instead
84 // a simple builtin function with a special name.
85 (List(Bind.create(BuiltinFunctionCall.create("SKOLEM",term),y)),y)
86 }
87 val classVisitor = new RDFoxClassExprConverter(term1,skolem)
88 val classResult = expr.getFiller.accept(classVisitor)
89 val propertyVisitor = new RDFoxPropertyExprConverter(term, term1, skolem)
90 val propertyResult = expr.getProperty.accept(propertyVisitor)
91 RDFoxRuleShards(
92 classResult.res ++ propertyResult,
93 fun ++ classResult.ext
94 )
95 }
96
97 // OWLObjectMaxCardinality
98 override
99 def visit(expr : OWLObjectMaxCardinality) : RDFoxRuleShards = {
100 // TODO: again, no hardcoded variables
101 val vars = List(Variable.create("y"),Variable.create("z"))
102 val classResult = RDFoxClassExprConverter.merge(
103 vars.map(new RDFoxClassExprConverter(_,skolem))
104 .map(expr.getFiller.accept(_))
105 )
106 val propertyResult =
107 vars.map(new RDFoxPropertyExprConverter(term,_,skolem))
108 .map(expr.getProperty.accept(_))
109 .flatten
110 RDFoxRuleShards(
111 List(Atom.create(Predicate.create("owl:sameAs"),vars(0),vars(1))),
112 classResult.res ++ propertyResult
113 )
114 }
115
116 def doDefault(expr : OWLClassExpression) : RDFoxRuleShards =
117 RDFoxRuleShards(List(),List())
118
119} // class RDFoxClassExprConverter
diff --git a/src/main/scala/example/RDFoxPropertyExprConverter.scala b/src/main/scala/example/RDFoxPropertyExprConverter.scala
new file mode 100644
index 0000000..2885ed9
--- /dev/null
+++ b/src/main/scala/example/RDFoxPropertyExprConverter.scala
@@ -0,0 +1,23 @@
1package rsacomb
2
3import org.semanticweb.owlapi.model.{OWLPropertyExpression, OWLObjectProperty}
4import org.semanticweb.owlapi.model.OWLPropertyExpressionVisitorEx
5
6import tech.oxfordsemantic.jrdfox.logic.{Atom, Predicate, Term, Variable, Literal}
7
8import rsacomb.SkolemStrategy
9
10class RDFoxPropertyExprConverter(term1 : Term, term2 : Term, skolem : SkolemStrategy)
11 extends OWLPropertyExpressionVisitorEx[List[Atom]]
12{
13
14 override
15 def visit(expr : OWLObjectProperty) : List[Atom] = {
16 val name = expr.getIRI.getIRIString
17 List(Atom.create(Predicate.create(name), term1, term2))
18 }
19
20 def doDefault(expr : OWLPropertyExpression) : List[Atom] = List()
21
22} // class RDFoxPropertyExprConverter
23
diff --git a/src/main/scala/example/RDFoxRuleShards.scala b/src/main/scala/example/RDFoxRuleShards.scala
new file mode 100644
index 0000000..bce31d2
--- /dev/null
+++ b/src/main/scala/example/RDFoxRuleShards.scala
@@ -0,0 +1,6 @@
1package rsacomb
2
3import tech.oxfordsemantic.jrdfox.logic.{Rule, Atom, Literal}
4
5case class RDFoxRuleShards(res : List[Atom], ext : List[Literal])
6
diff --git a/src/main/scala/example/RSAComb.scala b/src/main/scala/example/RSAComb.scala
new file mode 100644
index 0000000..bc94a8d
--- /dev/null
+++ b/src/main/scala/example/RSAComb.scala
@@ -0,0 +1,138 @@
1package rsacomb
2
3import java.io.File
4import java.util.HashMap
5import java.util.stream.{Stream,Collectors}
6
7import org.semanticweb.owlapi.apibinding.OWLManager
8import org.semanticweb.owlapi.model.{AxiomType, ClassExpressionType, OWLObjectSomeValuesFrom}
9import org.semanticweb.owlapi.model.{OWLAxiom, OWLSubClassOfAxiom, OWLEquivalentClassesAxiom}
10import org.semanticweb.owlapi.model.OWLClassExpression
11import org.semanticweb.owlapi.model.OWLOntology
12import org.semanticweb.owlapi.model.OWLOntologyManager
13import org.semanticweb.owlapi.model.parameters.Imports
14
15import tech.oxfordsemantic.jrdfox.Prefixes
16import tech.oxfordsemantic.jrdfox.client.{ConnectionFactory, ServerConnection, DataStoreConnection}
17import tech.oxfordsemantic.jrdfox.client.UpdateType
18import tech.oxfordsemantic.jrdfox.logic.{Rule, Atom, Literal, Predicate, Term, Variable}
19import tech.oxfordsemantic.jrdfox.logic.{Bind, BuiltinFunctionCall}
20
21import scala.collection.JavaConverters._
22
23import rsacomb.SkolemStrategy
24
25class RSA(ontology : OWLOntology) {
26
27 /* Alternative constructor(s) */
28 def this(file : File) = this(RSA.loadOntology(file))
29
30 def getOntology : OWLOntology = ontology
31
32} // class RSA
33
34object RSA {
35
36 def loadOntology( onto : File ) : OWLOntology = {
37 /* Retrieve ontology manager */
38 val manager : OWLOntologyManager = OWLManager.createOWLOntologyManager()
39 /* Retrieve ontology */
40 manager.loadOntologyFromOntologyDocument(onto)
41 }
42
43 def isRSA( onto : OWLOntology ) : Boolean = {
44 /* TODO: Steps for RSA check
45 * 1) convert ontology axioms into LP rules
46 * 2) call RDFox on the onto and compute materialization
47 * 3) build graph from E(x,y) facts
48 * 4) check if the graph is tree-like
49 */
50
51 /* Ontology axiom convertion into LP rules */
52 for {
53 axiom <- onto.tboxAxioms(Imports.EXCLUDED).collect(Collectors.toList()).asScala
54 visitor = new RDFoxAxiomConverter(Variable.create("x"), SkolemStrategy.Constant(axiom.toString))
55 rule <- axiom.accept(visitor)
56 } yield println(rule)
57
58 /* Return true for now... */
59 true
60 }
61
62} // object RSA
63
64object RSAComb {
65
66 val help : String = """
67 rsacomb - combined approach for CQ answering for RSA ontologies.
68
69 USAGE
70 rsacomb <path/to/ontology.owl> <path/to/query.sparql>
71
72 where
73 the ontology is expected to be an OWL file and the (single)
74 query a SPARQL query file.
75 """
76
77 def main( args : Array[String] ) : Unit = {
78
79 /* Simple arguments handling
80 *
81 * TODO: use something better later on
82 */
83
84 if (args.length < 2) {
85 println(help)
86 return ()
87 }
88
89 val ontologyPath = new File(args(0))
90 val queryPath = new File(args(1))
91
92 if (!ontologyPath.isFile || !queryPath.isFile) {
93 println("The provided arguments are not regular files.\n\n")
94 println(help)
95 return ()
96 }
97
98 /* Create RSA object from generic OWLOntology
99 *
100 * TODO: It might be required to check if the ontology in input is
101 * Horn-ALCHOIQ. At the moment we are assuming this is always the
102 * case.
103 */
104 val rsa = new RSA(ontologyPath)
105 RSA.isRSA(rsa.getOntology)
106
107 /* Build canonical model */
108 //val tboxCanon = rsa.canonicalModel()
109
110 /* Load query */
111 //val query = ...
112
113 /* Compute the filtering program from the given query */
114 //val tboxFilter = rsa.filteringProgram(query)
115
116 /* ... */
117
118 /* DEBUG ONLY */
119 println("Ok!")
120 }
121}
122
123/* Notes:
124 *
125 * To establish a connection with a local RDFox instance, do the
126 * following:
127 *
128 * ```
129 * val serverConnection : ServerConnection = ConnectionFactory.newServerConnection("rdfox:local", "", "")
130 * serverConnection.createDataStore("test","seq",new HashMap())
131 * val dataStoreConnection : DataStoreConnection = serverConnection.newDataStoreConnection("test")
132 * dataStoreConnection.importData(
133 * UpdateType.ADDITION,
134 * Prefixes.s_emptyPrefixes,
135 * new File("./path/to/file")
136 * )
137 * ```
138 */
diff --git a/src/main/scala/example/SkolemStrategy.scala b/src/main/scala/example/SkolemStrategy.scala
new file mode 100644
index 0000000..9df167f
--- /dev/null
+++ b/src/main/scala/example/SkolemStrategy.scala
@@ -0,0 +1,46 @@
1package rsacomb
2
3sealed trait SkolemStrategy
4
5object SkolemStrategy {
6 // TODO: might want to use something else other than `hashCode` as a
7 // function to generate a fresh function/constant
8
9 /* No skolemization at all.
10 *
11 * From
12 * ∃R.A ⊑ B
13 * to
14 * R(x,y), B(y) -> B(x)
15 */
16 case object None extends SkolemStrategy
17
18 /* Functional skolemization
19 *
20 * From
21 * A ⊑ ∃R.B
22 * to
23 * A(y) -> R(x,f(x)), B(f(x))
24 * for f, fresh function associated with the input axiom
25 */
26 case class Standard(func : String) extends SkolemStrategy
27 object Standard {
28 def apply(axiom : String) = new Standard(genFunctionString(axiom))
29 def genFunctionString(str : String) = "f_" ++ str.hashCode.toString
30 }
31
32 /* Functional skolemization
33 *
34 * From
35 * A ⊑ ∃R.B
36 * to
37 * A(y) -> R(x,c), B(c)
38 * for c, fresh constant associated with the input axiom
39 */
40 case class Constant(const : String) extends SkolemStrategy
41 object Constant {
42 def apply(axiom : String) = new Constant(genConstantString(axiom))
43 def genConstantString(str : String) = "internal:c_" ++ str.hashCode.toString
44 }
45}
46
diff --git a/src/test/scala/buzz/OWLAxiomSpec.scala b/src/test/scala/buzz/OWLAxiomSpec.scala
new file mode 100644
index 0000000..b6a44f4
--- /dev/null
+++ b/src/test/scala/buzz/OWLAxiomSpec.scala
@@ -0,0 +1,302 @@
1package rsacomb
2
3import java.util.ArrayList
4import org.scalatest.{FlatSpec, Matchers, LoneElement}
5
6import uk.ac.manchester.cs.owl.owlapi.{OWLSubClassOfAxiomImpl}
7import uk.ac.manchester.cs.owl.owlapi.{OWLClassImpl, OWLObjectSomeValuesFromImpl, OWLObjectIntersectionOfImpl, OWLObjectOneOfImpl, OWLObjectAllValuesFromImpl, OWLObjectMaxCardinalityImpl, OWLNamedIndividualImpl}
8import uk.ac.manchester.cs.owl.owlapi.{OWLObjectPropertyImpl}
9import org.semanticweb.owlapi.model.{OWLAxiom,IRI}
10
11import tech.oxfordsemantic.jrdfox.logic.{Rule,Bind,BuiltinFunctionCall}
12import tech.oxfordsemantic.jrdfox.logic.{Atom, Predicate, Term, Variable, Individual}
13
14object OWLAxiomSpec {
15
16 // IRI
17 val iri_Professor = IRI.create("univ:Professor")
18 val iri_Female = IRI.create("std:Female")
19 val iri_Student = IRI.create("univ:Student")
20 val iri_PartTimeStudent = IRI.create("univ:PartTimeStudent")
21 val iri_Worker = IRI.create("univ:Worker")
22 val iri_alice = IRI.create("univ:alice")
23 val iri_supervises = IRI.create("univ:supervises")
24 val iri_hasSupervisor = IRI.create("univ:hasSupervisor")
25 val iri_sameAs = IRI.create("owl:sameAs")
26
27 // RDFox Terms
28 val term_x = Variable.create("x")
29 val term_y = Variable.create("y")
30 val term_z = Variable.create("z")
31 val term_c1 = Individual.create("internal:c_1")
32 val term_c2 = Individual.create("internal:c_2")
33 val term_alice = Individual.create("univ:alice")
34
35 // RDFox Predicates
36 val pred_sameAs = Predicate.create("owl:sameAs")
37 val pred_Professor = Predicate.create(iri_Professor.getIRIString)
38 val pred_hasSupervisor = Predicate.create(iri_hasSupervisor.getIRIString)
39
40 // OWL Classes
41 // Name Class corresponding to
42 //
43 // Professor
44 //
45 val class_Professor = new OWLClassImpl(iri_Professor)
46 val class_Female = new OWLClassImpl(iri_Female)
47 val class_Student = new OWLClassImpl(iri_Student)
48 val class_PartTimeStudent = new OWLClassImpl(iri_PartTimeStudent)
49 val class_Worker = new OWLClassImpl(iri_Worker)
50 val class_OWLClass = class_Professor
51 // Class Conjunction corresponding to
52 //
53 // Student ∧ Worker
54 //
55 val class_OWLObjectIntersectionOf =
56 new OWLObjectIntersectionOfImpl(
57 class_Student, class_Worker
58 )
59 // Singleton Class corresponding to
60 //
61 // { alice }
62 //
63 val class_OWLObjectOneOf =
64 new OWLObjectOneOfImpl(
65 new OWLNamedIndividualImpl(iri_alice)
66 )
67 // Object Existential Restiction corresponding to
68 //
69 // ∃ hasSupervisor.Professor
70 //
71 val class_OWLObjectSomeValuesFrom =
72 new OWLObjectSomeValuesFromImpl(
73 new OWLObjectPropertyImpl(iri_hasSupervisor),
74 class_Professor
75 )
76 // Object Max Cardinality Restriction corresponding to
77 //
78 // ≤ 1 hasSupervisor . Professor
79 val class_OWLObjectMaxCardinality =
80 new OWLObjectMaxCardinalityImpl(
81 new OWLObjectPropertyImpl(iri_hasSupervisor),
82 1,
83 class_Professor
84 )
85
86 // OWL Axioms
87 // Axiom SubClassOf corresponding to
88 //
89 // Student ∧ Worker -> PartTimeStudent
90 //
91 val axiom_OWLSubClassOf1 =
92 new OWLSubClassOfAxiomImpl(
93 class_OWLObjectIntersectionOf,
94 class_PartTimeStudent,
95 new ArrayList()
96 )
97
98 // Axiom SubClassOf corresponding to
99 //
100 // Student -> ∃ hasSupervisor.Professor
101 //
102 val axiom_OWLSubClassOf2 =
103 new OWLSubClassOfAxiomImpl(
104 class_Student,
105 class_OWLObjectSomeValuesFrom,
106 new ArrayList()
107 )
108
109 // Axiom SubClassOf corresponding to
110 //
111 // ∃ hasSupervisor.Professor -> Student
112 //
113 val axiom_OWLSubClassOf3 =
114 new OWLSubClassOfAxiomImpl(
115 class_OWLObjectSomeValuesFrom,
116 class_Student,
117 new ArrayList()
118 )
119
120 // Axiom SubClassOf corresponding to
121 //
122 // Student -> { alice }
123 //
124 val axiom_OWLSubClassOf4 =
125 new OWLSubClassOfAxiomImpl(
126 class_Student,
127 class_OWLObjectOneOf,
128 new ArrayList()
129 )
130
131 // Axiom SubClassOf corresponding to
132 //
133 // Student -> ≤1 hasSupervisor.Professor
134 //
135 val axiom_OWLSubClassOf5 =
136 new OWLSubClassOfAxiomImpl(
137 class_Student,
138 class_OWLObjectMaxCardinality,
139 new ArrayList()
140 )
141
142 def convertAxiom(
143 axiom: OWLAxiom,
144 term: Term,
145 skolem: SkolemStrategy = SkolemStrategy.None
146 ) : List[Rule] = {
147 axiom.accept(RDFoxAxiomConverter(term,skolem))
148 }
149
150} // object OWLAxiomSpec
151
152class OWLAxiomSpec
153 extends FlatSpec with Matchers with LoneElement
154{
155 // Import required data
156 import OWLAxiomSpec._
157
158 // OWLSubClassOfAxiom #1
159 axiom_OWLSubClassOf1.toString should "be converted into a singleton List[Rule]" in {
160 val result = convertAxiom(axiom_OWLSubClassOf1,term_x)
161 result.loneElement shouldBe a [Rule]
162 }
163
164 it should "contain a conjuction of atoms (Student[?x],Worker[?x]) in the body of the rule" in {
165 val result = convertAxiom(axiom_OWLSubClassOf1,term_x)
166 val body = List(
167 Atom.create(Predicate.create(iri_Student.getIRIString),term_x),
168 Atom.create(Predicate.create(iri_Worker.getIRIString),term_x)
169 )
170 result.loneElement.getBody should contain theSameElementsAs body
171 }
172
173 it should "contain a single atom (PartTimeStudent[?x]) in the head of the rule" in {
174 val result = convertAxiom(axiom_OWLSubClassOf1,term_x)
175 val head = Atom.create(Predicate.create(iri_PartTimeStudent.getIRIString),term_x)
176 result.loneElement.getHead.loneElement should be (head)
177 }
178
179 // OWLSubClassOfAxiom #2 (w/ constant skolemization)
180 (axiom_OWLSubClassOf2.toString + "\n(w/ constant skolemization)") should
181 "be converted into a singleton List[Rule]" in
182 {
183 val skolem = SkolemStrategy.Constant(axiom_OWLSubClassOf2.toString)
184 val result = convertAxiom(axiom_OWLSubClassOf2,term_x,skolem)
185 result.loneElement shouldBe a [Rule]
186 }
187
188 it should "contain a single atom (Student[?x]) in the body of the rule" in {
189 val skolem = SkolemStrategy.Constant(axiom_OWLSubClassOf2.toString)
190 val result = convertAxiom(axiom_OWLSubClassOf2,term_x,skolem)
191 val body = Atom.create(Predicate.create(iri_Student.getIRIString),term_x)
192 result.loneElement.getBody.loneElement should equal (body)
193 }
194
195 it should "contain a conjuction of atoms (hasSupervisor[?x,?c],Professor[?c]) in the head of the rule" in {
196 val skolem = SkolemStrategy.Constant(axiom_OWLSubClassOf2.toString)
197 val result = convertAxiom(axiom_OWLSubClassOf2,term_x,skolem)
198 val term_c = Individual.create(skolem.const)
199 val head = List(
200 Atom.create(Predicate.create(iri_hasSupervisor.getIRIString),term_x,term_c),
201 Atom.create(Predicate.create(iri_Professor.getIRIString),term_c)
202 )
203 result.loneElement.getHead should contain theSameElementsAs (head)
204 }
205
206 // OWLSubClassOfAxiom #2 (w/ skolemization)
207 (axiom_OWLSubClassOf2.toString + "\n(w/ skolemization)") should
208 "be converted into a singleton List[Rule]" in
209 {
210 val skolem = SkolemStrategy.Standard(axiom_OWLSubClassOf2.toString)
211 val result = convertAxiom(axiom_OWLSubClassOf2, term_x, skolem)
212 result.loneElement shouldBe a [Rule]
213 }
214
215 it should "contain an atom (Student[?x]) in the body of the rule" in {
216 val skolem = SkolemStrategy.Standard(axiom_OWLSubClassOf2.toString)
217 val result = convertAxiom(axiom_OWLSubClassOf2, term_x, skolem)
218 val body = Atom.create(Predicate.create(iri_Student.getIRIString),term_x)
219 result.loneElement.getBody should contain (body)
220 }
221
222 it should "contain a built-in function call (BIND(?y,SKOLEM(?f,?x))) in the body of the rule" in {
223 val skolem = SkolemStrategy.Standard(axiom_OWLSubClassOf2.toString)
224 val result = convertAxiom(axiom_OWLSubClassOf2, term_x, skolem)
225 val call = Bind.create(BuiltinFunctionCall.create("SKOLEM",term_x),term_y)
226 result.loneElement.getBody should contain (call)
227 }
228
229 it should "contain a conjuction of atom (hasSupervisor[?x,?y],Professor[?y]) in the head of the rule" in {
230 val skolem = SkolemStrategy.Standard(axiom_OWLSubClassOf2.toString)
231 val result = convertAxiom(axiom_OWLSubClassOf2, term_x, skolem)
232 val head = List(
233 Atom.create(Predicate.create(iri_hasSupervisor.getIRIString),term_x,term_y),
234 Atom.create(Predicate.create(iri_Professor.getIRIString),term_y)
235 )
236 result.loneElement.getHead should contain theSameElementsAs head
237 }
238
239 // OWLSubClassOfAxiom #3
240 axiom_OWLSubClassOf3.toString should "be converted into a singleton List[Rule]" in {
241 val result = convertAxiom(axiom_OWLSubClassOf3,term_x)
242 result.loneElement shouldBe a [Rule]
243 }
244
245 it should "contain a conjunction of atoms (hasSupervisor[?x,?y],Professor[?y]) in the body of the rule" in {
246 val result = convertAxiom(axiom_OWLSubClassOf3,term_x)
247 val body = List(
248 Atom.create(Predicate.create(iri_hasSupervisor.getIRIString),term_x,term_y),
249 Atom.create(Predicate.create(iri_Professor.getIRIString),term_y)
250 )
251 result.loneElement.getBody should contain theSameElementsAs body
252 }
253
254 it should "contain a single atom (Student[?x]) in the head of the rule" in {
255 val result = convertAxiom(axiom_OWLSubClassOf3, term_x)
256 val head = Atom.create(Predicate.create(iri_Student.getIRIString),term_x)
257 result.loneElement.getHead.loneElement should be (head)
258 }
259
260 // OWLSubClassOfAxiom #4
261 axiom_OWLSubClassOf4.toString should "be converted into a singleton List[Rule]" in {
262 val result = convertAxiom(axiom_OWLSubClassOf4,term_x)
263 result.loneElement shouldBe a [Rule]
264 }
265
266 it should "contain a single atoms (Student[?x]) in the body of the rule" in {
267 val result = convertAxiom(axiom_OWLSubClassOf4,term_x)
268 val body = Atom.create(Predicate.create(iri_Student.getIRIString),term_x)
269 result.loneElement.getBody.loneElement should be (body)
270 }
271
272 it should "contain a single atom (sameAs[?x,alice])) in the head of the rule" in {
273 val result = convertAxiom(axiom_OWLSubClassOf4, term_x)
274 val head = Atom.create(Predicate.create(iri_sameAs.getIRIString),term_x,term_alice)
275 result.loneElement.getHead.loneElement should be (head)
276 }
277
278 // OWLSubClassOfAxiom #5
279 axiom_OWLSubClassOf5.toString should "be converted into a singleton List[Rule]" in {
280 val result = convertAxiom(axiom_OWLSubClassOf5,term_x)
281 result.loneElement shouldBe a [Rule]
282 }
283
284 it should "contain a conjunction of atoms (...) in the body of the rule" in {
285 val result = convertAxiom(axiom_OWLSubClassOf5,term_x)
286 val body = List(
287 Atom.create(Predicate.create(iri_Student.getIRIString),term_x),
288 Atom.create(Predicate.create(iri_hasSupervisor.getIRIString),term_x,term_y),
289 Atom.create(Predicate.create(iri_Professor.getIRIString),term_y),
290 Atom.create(Predicate.create(iri_hasSupervisor.getIRIString),term_x,term_z),
291 Atom.create(Predicate.create(iri_Professor.getIRIString),term_z)
292 )
293 result.loneElement.getBody should contain theSameElementsAs body
294 }
295
296 it should "contain a single atom (sameAs[?x,?z])) in the head of the rule" in {
297 val result = convertAxiom(axiom_OWLSubClassOf5, term_x)
298 val head = Atom.create(Predicate.create(iri_sameAs.getIRIString),term_y,term_z)
299 result.loneElement.getHead.loneElement should be (head)
300 }
301
302} // class OWLAxiomSpec
diff --git a/src/test/scala/buzz/OWLClassSpec.scala b/src/test/scala/buzz/OWLClassSpec.scala
new file mode 100644
index 0000000..df10e19
--- /dev/null
+++ b/src/test/scala/buzz/OWLClassSpec.scala
@@ -0,0 +1,259 @@
1package rsacomb
2
3import org.scalatest.{FlatSpec, Matchers, LoneElement}
4
5import uk.ac.manchester.cs.owl.owlapi.{OWLClassImpl, OWLObjectSomeValuesFromImpl, OWLObjectIntersectionOfImpl, OWLObjectOneOfImpl, OWLObjectAllValuesFromImpl, OWLObjectMaxCardinalityImpl, OWLNamedIndividualImpl}
6import uk.ac.manchester.cs.owl.owlapi.{OWLObjectPropertyImpl}
7import org.semanticweb.owlapi.model.IRI
8
9import tech.oxfordsemantic.jrdfox.logic.{Bind,BuiltinFunctionCall}
10import tech.oxfordsemantic.jrdfox.logic.{Atom, Predicate, Term, Variable, Individual}
11
12import rsacomb.RDFoxRuleShards
13
14object OWLClassSpec {
15
16 // IRI
17 val iri_Professor = IRI.create("univ:Professor")
18 val iri_Female = IRI.create("std:Female")
19 val iri_Student = IRI.create("univ:Student")
20 val iri_Worker = IRI.create("univ:Worker")
21 val iri_alice = IRI.create("univ:alice")
22 val iri_supervises = IRI.create("univ:supervises")
23 val iri_hasSupervisor = IRI.create("univ:hasSupervisor")
24
25 // RDFox Terms
26 val term_x = Variable.create("x")
27 val term_y = Variable.create("y")
28 val term_c1 = Individual.create("internal:c_1")
29 val term_c2 = Individual.create("internal:c_2")
30 val term_alice = Individual.create("univ:alice")
31
32 // RDFox Predicates
33 val pred_sameAs = Predicate.create("owl:sameAs")
34 val pred_Professor = Predicate.create(iri_Professor.getIRIString)
35 val pred_hasSupervisor = Predicate.create(iri_hasSupervisor.getIRIString)
36
37 // OWL Classes
38 // Name Class corresponding to
39 //
40 // Professor
41 //
42 val class_Professor = new OWLClassImpl(iri_Professor)
43 val class_Female = new OWLClassImpl(iri_Female)
44 val class_Student = new OWLClassImpl(iri_Student)
45 val class_Worker = new OWLClassImpl(iri_Worker)
46 val class_OWLClass = class_Professor
47
48 // Class Conjunction corresponding to
49 //
50 // Female ∧ Student ∧ Worker
51 //
52 val class_OWLObjectIntersectionOf =
53 new OWLObjectIntersectionOfImpl(
54 class_Female, class_Student, class_Worker
55 )
56 // Singleton Class corresponding to
57 //
58 // { alice }
59 //
60 val class_OWLObjectOneOf =
61 new OWLObjectOneOfImpl(
62 new OWLNamedIndividualImpl(iri_alice)
63 )
64 // Object Existential Restiction corresponding to
65 //
66 // ∃ hasSupervisor.Professor
67 //
68 val class_OWLObjectSomeValuesFrom =
69 new OWLObjectSomeValuesFromImpl(
70 new OWLObjectPropertyImpl(iri_hasSupervisor),
71 class_Professor
72 )
73 // Object Max Cardinality Restriction corresponding to
74 //
75 // ≤1 hasSupervisor.Professor
76 val class_OWLObjectMaxCardinality =
77 new OWLObjectMaxCardinalityImpl(
78 new OWLObjectPropertyImpl(iri_hasSupervisor),
79 1,
80 class_Professor
81 )
82} // object OWLClassSpec
83
84class OWLClassSpec
85 extends FlatSpec with Matchers with LoneElement
86{
87 // Import required data
88 import OWLClassSpec._
89
90 // OWLClass
91 class_OWLClass.toString should "be converted into a RDFoxRuleShards" in {
92 val visitor = RDFoxClassExprConverter(term_x)
93 val result = class_OWLClass.accept(visitor)
94 result shouldBe a [RDFoxRuleShards]
95 }
96
97 it should "have a single Atom in its result list" in {
98 val visitor = RDFoxClassExprConverter(term_x)
99 val result = class_OWLClass.accept(visitor)
100 result.res.loneElement shouldBe an [Atom]
101 }
102
103 it should "have an empty extension list" in {
104 val visitor = RDFoxClassExprConverter(term_x)
105 val result = class_OWLClass.accept(visitor)
106 result.ext shouldBe empty
107 }
108
109 // OWLObjectIntersectionOf
110 class_OWLObjectIntersectionOf.toString should "be converted into a RDFoxRuleShards" in {
111 val visitor = RDFoxClassExprConverter(term_x)
112 val result = class_OWLObjectIntersectionOf.accept(visitor)
113 result shouldBe a [RDFoxRuleShards]
114 }
115
116 it should "be converted in the union of its converted conjuncts" in {
117 val visitor = RDFoxClassExprConverter(term_x)
118 val result1= class_OWLObjectIntersectionOf.accept(visitor)
119 val result2 = RDFoxClassExprConverter.merge(List(
120 class_Female.accept(visitor),
121 class_Student.accept(visitor),
122 class_Worker.accept(visitor)
123 ))
124 result1.res should contain theSameElementsAs result2.res
125 result1.ext should contain theSameElementsAs result2.ext
126 }
127
128 // OWLObjectOneOf
129 class_OWLObjectOneOf.toString should "be converted into a RDFoxRuleShards" in {
130 val visitor = RDFoxClassExprConverter(term_x)
131 val result = class_OWLObjectOneOf.accept(visitor)
132 result shouldBe a [RDFoxRuleShards]
133 }
134
135 it should "be converted into a single <owl:sameAs> Atom" in {
136 val visitor = RDFoxClassExprConverter(term_x)
137 val result = class_OWLObjectOneOf.accept(visitor)
138 result.res.loneElement should (be (a [Atom]) and have ('predicate (pred_sameAs)))
139 }
140
141 it should "have an empty extension list" in {
142 val visitor = RDFoxClassExprConverter(term_x)
143 val result = class_OWLObjectOneOf.accept(visitor)
144 result.ext shouldBe empty
145 }
146
147 // OWLObjectSomeValuesFrom
148 (class_OWLObjectSomeValuesFrom.toString ++ " w/o skolemization") should
149 "be converted into a RDFoxRuleShards" in {
150 val visitor = RDFoxClassExprConverter(term_x,SkolemStrategy.None)
151 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
152 result shouldBe a [RDFoxRuleShards]
153 }
154
155 it should "have exactly one unary Atom in its result list" in {
156 val visitor = RDFoxClassExprConverter(term_x,SkolemStrategy.None)
157 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
158 exactly (1, result.res) should (be (an [Atom]) and have ('numberOfArguments (1)))
159 }
160
161 it should "have exactly one binary Atom in its result list" in {
162 val visitor = RDFoxClassExprConverter(term_x,SkolemStrategy.None)
163 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
164 exactly (1, result.res) should (be (an [Atom]) and have ('numberOfArguments (2)))
165 }
166
167 it should "have an empty extension list" in {
168 val visitor = RDFoxClassExprConverter(term_x,SkolemStrategy.None)
169 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
170 result.ext shouldBe empty
171 }
172
173 (class_OWLObjectSomeValuesFrom.toString ++ " w/ skolemization") should
174 "be converted into a RDFoxRuleShards" in {
175 val skolem = SkolemStrategy.Standard(class_OWLObjectSomeValuesFrom.toString)
176 val visitor = RDFoxClassExprConverter(term_x,skolem)
177 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
178 result shouldBe a [RDFoxRuleShards]
179 }
180
181 it should "have exactly one unary Atom in its result list" in {
182 val skolem = SkolemStrategy.Standard(class_OWLObjectSomeValuesFrom.toString)
183 val visitor = RDFoxClassExprConverter(term_x,skolem)
184 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
185 exactly (1, result.res) should (be (an [Atom]) and have ('numberOfArguments (1)))
186 }
187
188 it should "have exactly one binary Atom in its result list" in {
189 val skolem = SkolemStrategy.Standard(class_OWLObjectSomeValuesFrom.toString)
190 val visitor = RDFoxClassExprConverter(term_x,skolem)
191 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
192 exactly (1, result.res) should (be (an [Atom]) and have ('numberOfArguments (2)))
193 }
194
195 it should "should have a single SKOLEM call in the extension list" in {
196 val skolem = SkolemStrategy.Standard(class_OWLObjectSomeValuesFrom.toString)
197 val visitor = RDFoxClassExprConverter(term_x,skolem)
198 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
199 result.ext.loneElement shouldBe a [Bind]
200 val builtin = result.ext.head.asInstanceOf[Bind].getBuiltinExpression
201 builtin should (be (a [BuiltinFunctionCall]) and have ('functionName ("SKOLEM")))
202 }
203
204 (class_OWLObjectSomeValuesFrom.toString ++ " w/ constant skolemization") should
205 "be converted into a RDFoxRuleShards" in {
206 val skolem = SkolemStrategy.Constant(class_OWLObjectSomeValuesFrom.toString)
207 val visitor = RDFoxClassExprConverter(term_x,skolem)
208 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
209 result shouldBe a [RDFoxRuleShards]
210 }
211
212 it should "have exactly one unary Atom in its result list" in {
213 val skolem = SkolemStrategy.Constant(class_OWLObjectSomeValuesFrom.toString)
214 val visitor = RDFoxClassExprConverter(term_x,skolem)
215 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
216 exactly (1, result.res) should (be (an [Atom]) and have ('numberOfArguments (1)))
217 }
218
219 it should "have exactly one binary Atom in its result list" in {
220 val skolem = SkolemStrategy.Constant(class_OWLObjectSomeValuesFrom.toString)
221 val visitor = RDFoxClassExprConverter(term_x,skolem)
222 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
223 exactly (1, result.res) should (be (an [Atom]) and have ('numberOfArguments (2)))
224 }
225
226 it should "have an empty extension list" in {
227 val skolem = SkolemStrategy.Constant(class_OWLObjectSomeValuesFrom.toString)
228 val visitor = RDFoxClassExprConverter(term_x,skolem)
229 val result = class_OWLObjectSomeValuesFrom.accept(visitor)
230 result.ext shouldBe empty
231 }
232
233 // OWLObjectMaxCardinalityImpl
234 class_OWLObjectMaxCardinality.toString should
235 "be converted into a RDFoxRuleShards" in {
236 val visitor = RDFoxClassExprConverter(term_x)
237 val result = class_OWLObjectMaxCardinality.accept(visitor)
238 result shouldBe a [RDFoxRuleShards]
239 }
240
241 it should "have a single <owl:sameAs> Atom in the result list" in {
242 val visitor = RDFoxClassExprConverter(term_x)
243 val result = class_OWLObjectMaxCardinality.accept(visitor)
244 result.res.loneElement should (be (an [Atom]) and have ('predicate (pred_sameAs)))
245 }
246
247 it should "have two unary Atoms in its extension list" in {
248 val visitor = RDFoxClassExprConverter(term_x)
249 val result = class_OWLObjectMaxCardinality.accept(visitor)
250 exactly (2, result.ext) should (be (an [Atom]) and have ('numberOfArguments (1)))
251 }
252
253 it should "have two binary Atoms in its extension list" in {
254 val visitor = RDFoxClassExprConverter(term_x)
255 val result = class_OWLObjectMaxCardinality.accept(visitor)
256 exactly (2, result.ext) should (be (an [Atom]) and have ('numberOfArguments (2)))
257 }
258
259} // class OWLClassSpec