From 30f1449365f51d3e138a3fcfd46aca2a4a4c55b9 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Tue, 1 Dec 2020 22:53:43 +0000 Subject: Add alternative conversion of axioms using switch-cases This is part of an effort to move away from the Java-style visitor pattern pushed by the OWLAPI and RDFox. Using a Scala approach will allow us to be more flexible in the long run. --- .../uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala | 104 +++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/test/scala/uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala (limited to 'src/test/scala') diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala new file mode 100644 index 0000000..35af464 --- /dev/null +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala @@ -0,0 +1,104 @@ +package rsacomb + +import org.scalatest.LoneElement +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers +import org.semanticweb.owlapi.apibinding.OWLManager +import org.semanticweb.owlapi.model.OWLOntologyManager + +import tech.oxfordsemantic.jrdfox.logic.datalog.TupleTableAtom +import tech.oxfordsemantic.jrdfox.logic.expression.{Variable, IRI} +import uk.ac.ox.cs.rsacomb.converter.RDFoxConverter +import uk.ac.ox.cs.rsacomb.suffix.{Empty, Forward, Backward, Inverse} +import uk.ac.ox.cs.rsacomb.converter.SkolemStrategy + +object RDFoxConverterSpec { + + val manager = OWLManager.createOWLOntologyManager() + val factory = manager.getOWLDataFactory + + val term0 = Variable.create("X") + val term1 = Variable.create("Y") + val iriString0 = "http://example.com/rsacomb/iri0" + val iriString1 = "http://example.com/rsacomb/iri1" + val iriString2 = "http://example.com/rsacomb/iri2" + val suffixes = Seq( + Empty, + Forward, + Backward, + Inverse, + Forward + Inverse, + Backward + Inverse + ) +} + +class RDFoxConverterSpec extends AnyFlatSpec with Matchers with LoneElement { + + import RDFoxConverterSpec._ + + "A class name" should "be converted into a single atom" in { + val cls = factory.getOWLClass(iriString0) + val atom = TupleTableAtom.rdf(term0, IRI.RDF_TYPE, IRI.create(iriString0)) + val (res, ext) = + RDFoxConverter.convert(cls, term0, List(), SkolemStrategy.None, Empty) + res.loneElement shouldEqual atom + ext shouldBe empty + } + + "A intersection of classes" should "be converted into the union of the conversion of the classes" in { + val cls0 = factory.getOWLClass(iriString0) + val cls1 = factory.getOWLClass(iriString1) + val cls2 = factory.getOWLClass(iriString2) + val conj = factory.getOWLObjectIntersectionOf(cls0, cls1, cls2) + val (res0, ext0) = + RDFoxConverter.convert(cls0, term0, List(), SkolemStrategy.None, Empty) + val (res1, ext1) = + RDFoxConverter.convert(cls1, term0, List(), SkolemStrategy.None, Empty) + val (res2, ext2) = + RDFoxConverter.convert(cls2, term0, List(), SkolemStrategy.None, Empty) + val (res, ext) = + RDFoxConverter.convert(conj, term0, List(), SkolemStrategy.None, Empty) + res should contain theSameElementsAs (res0 ::: res1 ::: res2) + ext should contain theSameElementsAs (ext0 ::: ext1 ::: ext2) + } + + "A singleton intersection" should "correspond to the conversion of the internal class" in { + val cls0 = factory.getOWLClass(iriString0) + val conj = factory.getOWLObjectIntersectionOf(cls0) + val (res0, ext0) = + RDFoxConverter.convert(cls0, term0, List(), SkolemStrategy.None, Empty) + val (res, ext) = + RDFoxConverter.convert(conj, term0, List(), SkolemStrategy.None, Empty) + res should contain theSameElementsAs res0 + ext should contain theSameElementsAs ext0 + } + + "An object property" should "be converted into an atom with matching predicate" in { + val prop = factory.getOWLObjectProperty(iriString0) + for (sx <- suffixes) { + val atom = + TupleTableAtom.rdf(term0, IRI.create(iriString0 :: sx), term1) + RDFoxConverter.convert(prop, term0, term1, sx) shouldEqual atom + } + } + + "The inverse of an object property" should "be converted into an atom with matching negated predicate" in { + val prop = factory.getOWLObjectProperty(iriString0) + val inv = factory.getOWLObjectInverseOf(prop) + for (sx <- Seq(Empty, Forward, Backward)) { + val atom = + TupleTableAtom.rdf(term0, IRI.create(iriString0 :: sx + Inverse), term1) + RDFoxConverter.convert(inv, term0, term1, sx) shouldEqual atom + } + } + + "A data property" should "be converted into an atom with matching predicate" in { + val prop = factory.getOWLDataProperty(iriString0) + for (suffix <- suffixes) { + val atom = + TupleTableAtom.rdf(term0, IRI.create(iriString0 :: suffix), term1) + RDFoxConverter.convert(prop, term0, term1, suffix) shouldEqual atom + } + } + +} -- cgit v1.2.3 From 42ba69cc2ad2ccc6ba0208a58e874eba5c911baf Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Wed, 2 Dec 2020 17:13:29 +0000 Subject: Fix tests failing due to recent changes --- .../uk/ac/ox/cs/rsacomb/CanonicalModelSpec.scala | 99 ++++++++++++++++------ .../uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala | 26 +++--- 2 files changed, 86 insertions(+), 39 deletions(-) (limited to 'src/test/scala') diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/CanonicalModelSpec.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/CanonicalModelSpec.scala index 3070ce3..0d07923 100644 --- a/src/test/scala/uk/ac/ox/cs/rsacomb/CanonicalModelSpec.scala +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/CanonicalModelSpec.scala @@ -15,6 +15,8 @@ import tech.oxfordsemantic.jrdfox.logic.expression.Variable import scala.collection.JavaConverters._ import uk.ac.ox.cs.rsacomb.RSAOntology +import uk.ac.ox.cs.rsacomb.converter.SkolemStrategy +import uk.ac.ox.cs.rsacomb.suffix.Empty import uk.ac.ox.cs.rsacomb.util.{RDFoxUtil, RSA} object Ontology1_CanonicalModelSpec { @@ -28,6 +30,7 @@ object Ontology1_CanonicalModelSpec { val ontology_path: File = new File("examples/example1.ttl") val ontology = RSAOntology(ontology_path) val program = ontology.canonicalModel + val converter = program.CanonicalModelConverter val roleR = new OWLObjectPropertyImpl(base("R")) val roleS = new OWLObjectPropertyImpl(base("S")) @@ -89,9 +92,13 @@ class Ontology1_CanonicalModelSpec } renderer.render(AsubClassOfD) should "be converted into a single Rule" in { - val varX = Variable.create("X") - val visitor = program.RuleGenerator - val rules = AsubClassOfD.accept(visitor) + val term = Variable.create("X") + val unsafe = ontology.unsafeRoles + val skolem = SkolemStrategy.None + val suffix = Empty + val (facts, rules) = + converter.convert(AsubClassOfD, term, unsafe, skolem, suffix) + facts shouldBe empty rules.loneElement shouldBe a[Rule] } @@ -154,10 +161,14 @@ class Ontology1_CanonicalModelSpec renderer.render( AsomeValuesFromSiC ) should "produce 1 rule" in { - val varX = Variable.create("X") - val visitor = program.RuleGenerator - val rules = AsomeValuesFromSiC.accept(visitor) - rules should have length 1 + val term = Variable.create("X") + val unsafe = ontology.unsafeRoles + val skolem = SkolemStrategy.None + val suffix = Empty + val (facts, rules) = + converter.convert(AsomeValuesFromSiC, term, unsafe, skolem, suffix) + facts shouldBe empty + rules.loneElement shouldBe a[Rule] } renderer.render( @@ -172,15 +183,18 @@ class Ontology1_CanonicalModelSpec ontology.cycle(DsomeValuesFromRB) should have size 48 } - it should "produce 5 rules" in { + it should "produce 48 facts and 98 rules" in { // Rule 1 provides 1 rule (split in 2) + 48 fact // Rule 2 provides 0 rules // Rule 3 provides 48 rule (split in 2) - // Then (1*2 + 48) + (0) + (48*2) = 146 - val varX = Variable.create("X") - val visitor = program.RuleGenerator - val rules = DsomeValuesFromRB.accept(visitor) - rules should have length 146 + val term = Variable.create("X") + val unsafe = ontology.unsafeRoles + val skolem = SkolemStrategy.None + val suffix = Empty + val (facts, rules) = + converter.convert(DsomeValuesFromRB, term, unsafe, skolem, suffix) + facts should have length 48 + rules should have length 98 } renderer.render( @@ -200,18 +214,26 @@ class Ontology1_CanonicalModelSpec // Rule 2 provides 0 rules // Rule 3 provides 32 rule (split in 2) // Then (1*2 + 32) + (0) + (32*2) = 98 - val varX = Variable.create("X") - val visitor = program.RuleGenerator - val rules = DsomeValuesFromRB.accept(visitor) - rules should have length 146 + val term = Variable.create("X") + val unsafe = ontology.unsafeRoles + val skolem = SkolemStrategy.None + val suffix = Empty + val (facts, rules) = + converter.convert(BsomeValuesFromSD, term, unsafe, skolem, suffix) + facts should have length 32 + rules should have length 66 } renderer.render( SsubPropertyOfT ) should "produce 2 rules" in { - val varX = Variable.create("X") - val visitor = program.RuleGenerator - val rules = SsubPropertyOfT.accept(visitor) + val term = Variable.create("X") + val unsafe = ontology.unsafeRoles + val skolem = SkolemStrategy.None + val suffix = Empty + val (facts, rules) = + converter.convert(SsubPropertyOfT, term, unsafe, skolem, suffix) + facts shouldBe empty rules should have length 2 } @@ -228,6 +250,7 @@ object Ontology2_CanonicalModelSpec { val ontology_path: File = new File("examples/example2.owl") val ontology = RSAOntology(ontology_path) val program = ontology.canonicalModel + val converter = program.CanonicalModelConverter val roleR = new OWLObjectPropertyImpl(base("R")) val roleS = new OWLObjectPropertyImpl(base("S")) @@ -332,8 +355,13 @@ class Ontology2_CanonicalModelSpec renderer.render( AsomeValuesFromRB ) should "produce 1 rule" in { - val visitor = program.RuleGenerator - val rules = AsomeValuesFromRB.accept(visitor) + val term = Variable.create("X") + val unsafe = ontology.unsafeRoles + val skolem = SkolemStrategy.None + val suffix = Empty + val (facts, rules) = + converter.convert(AsomeValuesFromRB, term, unsafe, skolem, suffix) + facts shouldBe empty rules should have length 1 } @@ -342,8 +370,13 @@ class Ontology2_CanonicalModelSpec renderer.render( BsomeValuesFromSC ) should "produce 1 rule" in { - val visitor = program.RuleGenerator - val rules = BsomeValuesFromSC.accept(visitor) + val term = Variable.create("X") + val unsafe = ontology.unsafeRoles + val skolem = SkolemStrategy.None + val suffix = Empty + val (facts, rules) = + converter.convert(BsomeValuesFromSC, term, unsafe, skolem, suffix) + facts shouldBe empty rules should have length 1 } @@ -352,8 +385,13 @@ class Ontology2_CanonicalModelSpec renderer.render( CsomeValuesFromTD ) should "produce 1 rule" in { - val visitor = program.RuleGenerator - val rules = CsomeValuesFromTD.accept(visitor) + val term = Variable.create("X") + val unsafe = ontology.unsafeRoles + val skolem = SkolemStrategy.None + val suffix = Empty + val (facts, rules) = + converter.convert(CsomeValuesFromTD, term, unsafe, skolem, suffix) + facts shouldBe empty rules should have length 1 } @@ -362,8 +400,13 @@ class Ontology2_CanonicalModelSpec renderer.render( DsomeValuesFromPA ) should "produce 1 rule" in { - val visitor = program.RuleGenerator - val rules = DsomeValuesFromPA.accept(visitor) + val term = Variable.create("X") + val unsafe = ontology.unsafeRoles + val skolem = SkolemStrategy.None + val suffix = Empty + val (facts, rules) = + converter.convert(DsomeValuesFromPA, term, unsafe, skolem, suffix) + facts shouldBe empty rules should have length 1 } diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala index 35af464..e2da6e4 100644 --- a/src/test/scala/uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala @@ -32,7 +32,11 @@ object RDFoxConverterSpec { ) } -class RDFoxConverterSpec extends AnyFlatSpec with Matchers with LoneElement { +class RDFoxConverterSpec + extends AnyFlatSpec + with Matchers + with LoneElement + with RDFoxConverter { import RDFoxConverterSpec._ @@ -40,7 +44,7 @@ class RDFoxConverterSpec extends AnyFlatSpec with Matchers with LoneElement { val cls = factory.getOWLClass(iriString0) val atom = TupleTableAtom.rdf(term0, IRI.RDF_TYPE, IRI.create(iriString0)) val (res, ext) = - RDFoxConverter.convert(cls, term0, List(), SkolemStrategy.None, Empty) + convert(cls, term0, List(), SkolemStrategy.None, Empty) res.loneElement shouldEqual atom ext shouldBe empty } @@ -51,13 +55,13 @@ class RDFoxConverterSpec extends AnyFlatSpec with Matchers with LoneElement { val cls2 = factory.getOWLClass(iriString2) val conj = factory.getOWLObjectIntersectionOf(cls0, cls1, cls2) val (res0, ext0) = - RDFoxConverter.convert(cls0, term0, List(), SkolemStrategy.None, Empty) + convert(cls0, term0, List(), SkolemStrategy.None, Empty) val (res1, ext1) = - RDFoxConverter.convert(cls1, term0, List(), SkolemStrategy.None, Empty) + convert(cls1, term0, List(), SkolemStrategy.None, Empty) val (res2, ext2) = - RDFoxConverter.convert(cls2, term0, List(), SkolemStrategy.None, Empty) + convert(cls2, term0, List(), SkolemStrategy.None, Empty) val (res, ext) = - RDFoxConverter.convert(conj, term0, List(), SkolemStrategy.None, Empty) + convert(conj, term0, List(), SkolemStrategy.None, Empty) res should contain theSameElementsAs (res0 ::: res1 ::: res2) ext should contain theSameElementsAs (ext0 ::: ext1 ::: ext2) } @@ -66,9 +70,9 @@ class RDFoxConverterSpec extends AnyFlatSpec with Matchers with LoneElement { val cls0 = factory.getOWLClass(iriString0) val conj = factory.getOWLObjectIntersectionOf(cls0) val (res0, ext0) = - RDFoxConverter.convert(cls0, term0, List(), SkolemStrategy.None, Empty) + convert(cls0, term0, List(), SkolemStrategy.None, Empty) val (res, ext) = - RDFoxConverter.convert(conj, term0, List(), SkolemStrategy.None, Empty) + convert(conj, term0, List(), SkolemStrategy.None, Empty) res should contain theSameElementsAs res0 ext should contain theSameElementsAs ext0 } @@ -78,7 +82,7 @@ class RDFoxConverterSpec extends AnyFlatSpec with Matchers with LoneElement { for (sx <- suffixes) { val atom = TupleTableAtom.rdf(term0, IRI.create(iriString0 :: sx), term1) - RDFoxConverter.convert(prop, term0, term1, sx) shouldEqual atom + convert(prop, term0, term1, sx) shouldEqual atom } } @@ -88,7 +92,7 @@ class RDFoxConverterSpec extends AnyFlatSpec with Matchers with LoneElement { for (sx <- Seq(Empty, Forward, Backward)) { val atom = TupleTableAtom.rdf(term0, IRI.create(iriString0 :: sx + Inverse), term1) - RDFoxConverter.convert(inv, term0, term1, sx) shouldEqual atom + convert(inv, term0, term1, sx) shouldEqual atom } } @@ -97,7 +101,7 @@ class RDFoxConverterSpec extends AnyFlatSpec with Matchers with LoneElement { for (suffix <- suffixes) { val atom = TupleTableAtom.rdf(term0, IRI.create(iriString0 :: suffix), term1) - RDFoxConverter.convert(prop, term0, term1, suffix) shouldEqual atom + convert(prop, term0, term1, suffix) shouldEqual atom } } -- cgit v1.2.3 From 91de03f187f298004d90708c5815e86134b10eae Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Wed, 2 Dec 2020 18:47:49 +0000 Subject: Make filtering program generate/load facts as facts --- .../uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src/test/scala') diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala index 71c9a99..86e0253 100644 --- a/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala @@ -65,24 +65,32 @@ class FilteringProgramSpec extends AnyFlatSpec with Matchers { import FilteringProgramSpec._ - "CQ 0" should "generate 30 rules" in { + "CQ 0" should "generate 27 rules and 3 facts" in { val cq = ConjunctiveQuery(cq0).get - FilteringProgram(cq, constants).rules should have length 30 + val filter = FilteringProgram(cq, constants) + filter.facts should have length 3 + filter.rules should have length 27 } "CQ 1" should "generate 15 rules" in { val cq = ConjunctiveQuery(cq1).get - FilteringProgram(cq, List()).rules should have length 15 + val filter = FilteringProgram(cq, List()) + filter.facts shouldBe empty + filter.rules should have length 15 } "CQ 2" should "generate 51 rules" in { val cq = ConjunctiveQuery(cq2).get - FilteringProgram(cq, List()).rules should have length 51 + val filter = FilteringProgram(cq, List()) + filter.facts shouldBe empty + filter.rules should have length 51 } "BCQ 0" should "generate 46 rules" in { val cq = ConjunctiveQuery(bcq0).get - FilteringProgram(cq, constants).rules should have length 46 + val filter = FilteringProgram(cq, constants) + filter.facts should have length 3 + filter.rules should have length 43 } } -- cgit v1.2.3