From 4df351d3b1d11fc045005323c38ba3528de631ea Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Wed, 18 Nov 2020 18:07:53 +0000 Subject: Rework RSA as a utility object --- src/main/scala/rsacomb/CanonicalModel.scala | 62 ++--- src/main/scala/rsacomb/FilteringProgram.scala | 284 ++++++++------------- src/main/scala/rsacomb/Main.scala | 232 +++++++++-------- src/main/scala/rsacomb/RDFoxAxiomConverter.scala | 2 +- .../scala/rsacomb/RDFoxClassExprConverter.scala | 19 +- .../scala/rsacomb/RDFoxPropertyExprConverter.scala | 2 +- src/main/scala/rsacomb/RDFoxUtil.scala | 113 -------- src/main/scala/rsacomb/RSA.scala | 105 +++++--- src/main/scala/rsacomb/RSAAtom.scala | 6 +- src/main/scala/rsacomb/RSAAxiom.scala | 13 + src/main/scala/rsacomb/RSAOntology.scala | 31 ++- .../scala/rsacomb/implicits/JavaCollections.scala | 13 + src/main/scala/rsacomb/implicits/RDFox.scala | 20 ++ src/main/scala/rsacomb/util/RDFoxHelpers.scala | 100 ++++++++ 14 files changed, 502 insertions(+), 500 deletions(-) delete mode 100644 src/main/scala/rsacomb/RDFoxUtil.scala create mode 100644 src/main/scala/rsacomb/implicits/JavaCollections.scala create mode 100644 src/main/scala/rsacomb/implicits/RDFox.scala create mode 100644 src/main/scala/rsacomb/util/RDFoxHelpers.scala (limited to 'src/main') diff --git a/src/main/scala/rsacomb/CanonicalModel.scala b/src/main/scala/rsacomb/CanonicalModel.scala index f7a45a7..5f781d1 100644 --- a/src/main/scala/rsacomb/CanonicalModel.scala +++ b/src/main/scala/rsacomb/CanonicalModel.scala @@ -24,16 +24,15 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{ } import suffix.{Empty, Forward, Backward, Inverse} +import util.RSA class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom { - // Makes working with IRIs less painful - import RDFoxUtil._ + import implicits.RDFox._ + import implicits.JavaCollections._ val named: List[Rule] = - ontology.individuals.map(a => - Rule.create(TupleTableAtom.rdf(a, IRI.RDF_TYPE, RSA.Named)) - ) + ontology.individuals.map(a => Rule.create(RSA.Named(a))) val rolesAdditionalRules: List[Rule] = { // Given a role (predicate) compute additional logic rules @@ -69,7 +68,7 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom { val varY = Variable.create("Y") val concepts = ontology.concepts.map(c => { Rule.create( - TupleTableAtom.rdf(varX, IRI.RDF_TYPE, IRI.THING), + RSA.Thing(varX), TupleTableAtom.rdf(varX, IRI.RDF_TYPE, c.getIRI) ) }) @@ -80,10 +79,7 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom { x.getInverse.getNamedProperty.getIRI.getIRIString :: Inverse } Rule.create( - List( - TupleTableAtom.rdf(varX, IRI.RDF_TYPE, IRI.THING), - TupleTableAtom.rdf(varY, IRI.RDF_TYPE, IRI.THING) - ), + List(RSA.Thing(varX), RSA.Thing(varY)), List(TupleTableAtom.rdf(varX, name, varY)) ) }) @@ -95,18 +91,15 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom { val varY = Variable.create("Y") val varZ = Variable.create("Z") List( + // Reflexivity + Rule.create(RSA.EquivTo(varX, varX), RSA.Thing(varX)), + // Simmetry + Rule.create(RSA.EquivTo(varY, varX), RSA.EquivTo(varX, varY)), + // Transitivity Rule.create( - TupleTableAtom.rdf(varX, RSA.EquivTo, varX), - TupleTableAtom.rdf(varX, IRI.RDF_TYPE, IRI.THING) - ), - Rule.create( - TupleTableAtom.rdf(varY, RSA.EquivTo, varX), - TupleTableAtom.rdf(varX, RSA.EquivTo, varY) - ), - Rule.create( - TupleTableAtom.rdf(varX, RSA.EquivTo, varZ), - TupleTableAtom.rdf(varX, RSA.EquivTo, varY), - TupleTableAtom.rdf(varY, RSA.EquivTo, varZ) + RSA.EquivTo(varX, varZ), + RSA.EquivTo(varX, varY), + RSA.EquivTo(varY, varZ) ) ) } @@ -129,21 +122,14 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom { private def rules1(axiom: OWLSubClassOfAxiom): List[Rule] = { val unfold = ontology.unfold(axiom).toList // Fresh Variables - val v0 = RSA.rsa("v0_" ++ RSA.hashed(axiom)) + val v0 = RSA("v0_" ++ axiom.hashed) val varX = Variable.create("X") - // Predicates + implicit val unfoldTerm = RSA(unfold.hashCode.toString) + // TODO: use axiom.toTriple instead val atomA: TupleTableAtom = { val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI TupleTableAtom.rdf(varX, IRI.RDF_TYPE, cls) } - def predIN(t: Term): TupleTableAtom = { - TupleTableAtom.rdf( - t, - RSA.rsa("IN"), - RSA.rsa(unfold.hashCode.toString) - ) - } - def notIn(t: Term): Negation = Negation.create(predIN(t)) val roleRf: TupleTableAtom = { val visitor = new RDFoxPropertyExprConverter(varX, v0, Forward) @@ -165,10 +151,10 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom { // returning facts as `Rule`s with true body. While this is correct // there is an easier way to import facts into RDFox. Are we able to // do that? - val facts = unfold.map(x => Rule.create(predIN(x))) + val facts = unfold.map(x => Rule.create(RSA.In(x))) val rules = List( - Rule.create(roleRf, atomA, notIn(varX)), - Rule.create(atomB, atomA, notIn(varX)) + Rule.create(roleRf, atomA, RSA.notIn(varX)), + Rule.create(atomB, atomA, RSA.notIn(varX)) ) facts ++ rules } @@ -180,9 +166,9 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom { .getProperty if (ontology.confl(roleR) contains roleR) { // Fresh Variables - val v0 = RSA.rsa("v0_" ++ RSA.hashed(axiom)) - val v1 = RSA.rsa("v1_" ++ RSA.hashed(axiom)) - val v2 = RSA.rsa("v2_" ++ RSA.hashed(axiom)) + val v0 = RSA("v0_" ++ axiom.hashed) + val v1 = RSA("v1_" ++ axiom.hashed) + val v2 = RSA("v2_" ++ axiom.hashed) // Predicates def atomA(t: Term): TupleTableAtom = { val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI @@ -220,7 +206,7 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom { .asInstanceOf[OWLObjectSomeValuesFrom] .getProperty // Fresh Variables - val v1 = RSA.rsa("v1_" ++ RSA.hashed(axiom)) + val v1 = RSA("v1_" ++ axiom.hashed) // Predicates def atomA(t: Term): TupleTableAtom = { val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI diff --git a/src/main/scala/rsacomb/FilteringProgram.scala b/src/main/scala/rsacomb/FilteringProgram.scala index af07ac3..5aaf5b0 100644 --- a/src/main/scala/rsacomb/FilteringProgram.scala +++ b/src/main/scala/rsacomb/FilteringProgram.scala @@ -29,44 +29,43 @@ import scala.collection.JavaConverters._ import implicits.RSAAtom import suffix.{RSASuffix, Forward, Backward} +import util.RSA class FilteringProgram(query: SelectQuery, constants: List[Term]) extends RSAAtom { /* Makes mplicit conversion OWLAPI IRI <-> RDFox IRI available */ - import RDFoxUtil._ + // import implicits.RDFox._ - lazy val variables = { - query.getQueryBody.getWherePattern match { + implicit val variables: (List[Term], List[Term]) = { + val all: Set[Variable] = query.getQueryBody.getWherePattern match { case b: ConjunctionPattern => { b.getConjuncts.asScala.toSet.flatMap { conj: QueryPattern => conj match { case c: TriplePattern => - Set(c.getSubject, c.getPredicate, c.getObject) - .filter(_.isInstanceOf[Variable]) + Set(c.getSubject, c.getPredicate, c.getObject).collect { + case v: Variable => v + } case _ => Set() } } } case _ => Set() } - }.toList - - val answer: List[Term] = if (query.getAllPossibleVariables) { - variables + (all.toList, List()) } else { - query.getSelection.asScala.map(_.getVariable).toList + val answer = query.getSelection.asScala.map(_.getVariable).toSet + (answer.toList, (all &~ answer).toList) } - val bounded: List[Term] = this.variables.filterNot(answer.contains(_)) + } + + val (answer, bounded) = variables - val facts: List[Rule] = constants.map(c => Rule.create(predNI(c))) + val facts: List[Rule] = constants.map(c => Rule.create(RSA.NI(c))) val rules: List[Rule] = this.generateFilteringProgram().map(reifyRule) ++ facts - private def predNI(t: Term): TupleTableAtom = - TupleTableAtom.rdf(t, IRI.RDF_TYPE, RSA.rsa("NI")) - /* NOTE: we are restricting to queries that contain conjunctions of * atoms for the time being. This might need to be reviewed in the * future. @@ -97,64 +96,54 @@ class FilteringProgram(query: SelectQuery, constants: List[Term]) val body = queryToBody(query.getQueryBody.getWherePattern) // Auxiliar predicates/helpers def not(atom: TupleTableAtom): BodyFormula = Negation.create(atom) - val predQM = - TupleTableAtom.create( - TupleTableName.create(RSA.rsa("QM").getIRI), - (answer ++ bounded): _* - ) - def predID(t1: Term, t2: Term) = - TupleTableAtom.create( - TupleTableName.create(RSA.rsa("ID").getIRI), - (answer ++ bounded).appended(t1).appended(t2): _* - ) - def predNAMED(t1: Term): TupleTableAtom = - TupleTableAtom.rdf(t1, IRI.RDF_TYPE, RSA.rsa("NAMED")) - def predTQ(t1: Term, t2: Term, sx: RSASuffix) = - TupleTableAtom.create( - TupleTableName.create(RSA.rsa("TQ" :: sx).getIRI), - (answer ++ bounded).appended(t1).appended(t2): _* - ) - def predAQ(t1: Term, t2: Term, sx: RSASuffix) = - TupleTableAtom.create( - TupleTableName.create(RSA.rsa("AQ" :: sx).getIRI), - (answer ++ bounded).appended(t1).appended(t2): _* - ) - val predFK = - TupleTableAtom.create( - TupleTableName.create(RSA.rsa("FK").getIRI), - (answer ++ bounded): _* - ) - val predSP = - TupleTableAtom.create( - TupleTableName.create(RSA.rsa("SP").getIRI), - (answer ++ bounded): _* - ) - val predANS = - TupleTableAtom.create( - TupleTableName.create(RSA.rsa("ANS").getIRI), - answer: _* - ) + // val predQM = + // TupleTableAtom.create( + // TupleTableName.create(RSA.Qm.getIRI), + // (answer ++ bounded): _* + // ) + // def predID(t1: Term, t2: Term) = + // TupleTableAtom.create( + // TupleTableName.create(RSA.rsa("ID").getIRI), + // (answer ++ bounded).appended(t1).appended(t2): _* + // ) + // def predNAMED(t1: Term): TupleTableAtom = + // TupleTableAtom.rdf(t1, IRI.RDF_TYPE, RSA.rsa("NAMED")) + // def predTQ(t1: Term, t2: Term, sx: RSASuffix) = + // TupleTableAtom.create( + // TupleTableName.create(RSA.rsa("TQ" :: sx).getIRI), + // (answer ++ bounded).appended(t1).appended(t2): _* + // ) + // def predAQ(t1: Term, t2: Term, sx: RSASuffix) = + // TupleTableAtom.create( + // TupleTableName.create(RSA.rsa("AQ" :: sx).getIRI), + // (answer ++ bounded).appended(t1).appended(t2): _* + // ) + // val predFK = + // TupleTableAtom.create( + // TupleTableName.create(RSA.rsa("FK").getIRI), + // (answer ++ bounded): _* + // ) + // val predSP = + // TupleTableAtom.create( + // TupleTableName.create(RSA.rsa("SP").getIRI), + // (answer ++ bounded): _* + // ) + // val predANS = + // TupleTableAtom.create( + // TupleTableName.create(RSA.rsa("ANS").getIRI), + // answer: _* + // ) /* Rule 1 */ - val r1 = Rule.create(predQM, body: _*) + val r1 = Rule.create(RSA.QM, body: _*) /* Rules 3x */ val r3a = for ((v, i) <- bounded.zipWithIndex) - yield Rule.create( - predID(RSA.rsa(i), RSA.rsa(i)), - predQM, - not(predNI(v)) - ) - val r3b = Rule.create( - predID(varV, varU), - predID(varU, varV) - ) - val r3c = Rule.create( - predID(varU, varW), - predID(varU, varV), - predID(varV, varW) - ) + yield Rule.create(RSA.ID(RSA(i), RSA(i)), RSA.QM, not(RSA.NI(v))) + val r3b = Rule.create(RSA.ID(varV, varU), RSA.ID(varU, varV)) + val r3c = + Rule.create(RSA.ID(varU, varW), RSA.ID(varU, varV), RSA.ID(varV, varW)) /* Rules 4x */ val r4a = for { @@ -163,20 +152,14 @@ class FilteringProgram(query: SelectQuery, constants: List[Term]) role2 <- body.filter(_.isRoleAssertion) if bounded contains (role2.getArguments.get(2)) } yield Rule.create( - predFK, + RSA.FK, role1 << Forward, role2 << Forward, - predID( - RSA.rsa(bounded.indexOf(role1.getArguments.get(2))), - RSA.rsa(bounded.indexOf(role2.getArguments.get(2))) + RSA.ID( + RSA(bounded.indexOf(role1.getArguments.get(2))), + RSA(bounded.indexOf(role2.getArguments.get(2))) ), - not( - TupleTableAtom.rdf( - role1.getArguments.get(0), - RSA.EquivTo, - role2.getArguments.get(0) - ) - ) + not(RSA.EquivTo(role1.getArguments.get(0), role2.getArguments.get(0))) ) val r4b = for { role1 <- body.filter(_.isRoleAssertion) @@ -184,20 +167,14 @@ class FilteringProgram(query: SelectQuery, constants: List[Term]) role2 <- body.filter(_.isRoleAssertion) if bounded contains (role2.getArguments.get(0)) } yield Rule.create( - predFK, + RSA.FK, role1 << Forward, role2 << Backward, - predID( - RSA.rsa(bounded.indexOf(role1.getArguments.get(2))), - RSA.rsa(bounded.indexOf(role2.getArguments.get(0))) + RSA.ID( + RSA(bounded.indexOf(role1.getArguments.get(2))), + RSA(bounded.indexOf(role2.getArguments.get(0))) ), - not( - TupleTableAtom.rdf( - role1.getArguments.get(0), - RSA.EquivTo, - role2.getArguments.get(2) - ) - ) + not(RSA.EquivTo(role1.getArguments.get(0), role2.getArguments.get(2))) ) val r4c = for { role1 <- body.filter(_.isRoleAssertion) @@ -205,20 +182,14 @@ class FilteringProgram(query: SelectQuery, constants: List[Term]) role2 <- body.filter(_.isRoleAssertion) if bounded contains (role2.getArguments.get(0)) } yield Rule.create( - predFK, + RSA.FK, role1 << Backward, role2 << Backward, - predID( - RSA.rsa(bounded.indexOf(role1.getArguments.get(0))), - RSA.rsa(bounded.indexOf(role2.getArguments.get(0))) + RSA.ID( + RSA(bounded.indexOf(role1.getArguments.get(0))), + RSA(bounded.indexOf(role2.getArguments.get(0))) ), - not( - TupleTableAtom.rdf( - role1.getArguments.get(2), - RSA.EquivTo, - role2.getArguments.get(2) - ) - ) + not(RSA.EquivTo(role1.getArguments.get(2), role2.getArguments.get(2))) ) /* Rules 5x */ @@ -234,18 +205,18 @@ class FilteringProgram(query: SelectQuery, constants: List[Term]) if bounded contains role2arg0 if bounded contains role2arg2 } yield Rule.create( - predID( - RSA.rsa(bounded indexOf role1arg0), - RSA.rsa(bounded indexOf role2arg0) + RSA.ID( + RSA(bounded indexOf role1arg0), + RSA(bounded indexOf role2arg0) ), role1 << Forward, role2 << Forward, - predID( - RSA.rsa(bounded indexOf role1arg2), - RSA.rsa(bounded indexOf role2arg2) + RSA.ID( + RSA(bounded indexOf role1arg2), + RSA(bounded indexOf role2arg2) ), - TupleTableAtom.rdf(role1arg0, RSA.EquivTo, role2arg0), - not(predNI(role1arg0)) + RSA.EquivTo(role1arg0, role2arg0), + not(RSA.NI(role1arg0)) ) val r5b = for { role1 <- body.filter(_.isRoleAssertion) @@ -259,18 +230,18 @@ class FilteringProgram(query: SelectQuery, constants: List[Term]) if bounded contains role2arg0 if bounded contains role2arg2 } yield Rule.create( - predID( - RSA.rsa(bounded indexOf role1arg0), - RSA.rsa(bounded indexOf role2arg2) + RSA.ID( + RSA(bounded indexOf role1arg0), + RSA(bounded indexOf role2arg2) ), role1 << Forward, role2 << Backward, - predID( - RSA.rsa(bounded indexOf role1arg2), - RSA.rsa(bounded indexOf role2arg0) + RSA.ID( + RSA(bounded indexOf role1arg2), + RSA(bounded indexOf role2arg0) ), - TupleTableAtom.rdf(role1arg0, RSA.EquivTo, role2arg2), - not(predNI(role1arg0)) + RSA.EquivTo(role1arg0, role2arg2), + not(RSA.NI(role1arg0)) ) val r5c = for { role1 <- body.filter(_.isRoleAssertion) @@ -284,18 +255,18 @@ class FilteringProgram(query: SelectQuery, constants: List[Term]) if bounded contains role2arg0 if bounded contains role2arg2 } yield Rule.create( - predID( - RSA.rsa(bounded indexOf role1arg2), - RSA.rsa(bounded indexOf role2arg2) + RSA.ID( + RSA(bounded indexOf role1arg2), + RSA(bounded indexOf role2arg2) ), role1 << Backward, role2 << Backward, - predID( - RSA.rsa(bounded indexOf role1arg0), - RSA.rsa(bounded indexOf role2arg0) + RSA.ID( + RSA(bounded indexOf role1arg0), + RSA(bounded indexOf role2arg0) ), - TupleTableAtom.rdf(role1arg2, RSA.EquivTo, role2arg2), - not(predNI(role1arg2)) + RSA.EquivTo(role1arg2, role2arg2), + not(RSA.NI(role1arg2)) ) /* Rules 6 */ @@ -308,10 +279,10 @@ class FilteringProgram(query: SelectQuery, constants: List[Term]) if bounded contains arg2 suffix <- Seq(Forward, Backward) } yield Rule.create( - predAQ(varV, varW, suffix), + RSA.AQ(varV, varW, suffix), role << suffix, - predID(RSA.rsa(bounded indexOf arg0), varV), - predID(RSA.rsa(bounded indexOf arg2), varW) + RSA.ID(RSA(bounded indexOf arg0), varV), + RSA.ID(RSA(bounded indexOf arg2), varW) ) } @@ -319,52 +290,33 @@ class FilteringProgram(query: SelectQuery, constants: List[Term]) val r7a = { for (suffix <- List(Forward, Backward)) yield Rule.create( - predTQ(varU, varV, suffix), - predAQ(varU, varV, suffix) + RSA.TQ(varU, varV, suffix), + RSA.AQ(varU, varV, suffix) ) } val r7b = { for (suffix <- List(Forward, Backward)) yield Rule.create( - predTQ(varU, varW, suffix), - predAQ(varU, varV, suffix), - predTQ(varV, varW, suffix) + RSA.TQ(varU, varW, suffix), + RSA.AQ(varU, varV, suffix), + RSA.TQ(varV, varW, suffix) ) } /* Rules 8x */ val r8a = - for (v <- answer) yield Rule.create(predSP, predQM, not(predNAMED(v))) + for (v <- answer) yield Rule.create(RSA.SP, RSA.QM, not(RSA.Named(v))) val r8b = - Rule.create(predSP, predFK) + Rule.create(RSA.SP, RSA.FK) val r8c = for (suffix <- List(Forward, Backward)) yield Rule.create( - predSP, - predTQ(varV, varV, suffix) + RSA.SP, + RSA.TQ(varV, varV, suffix) ) /* Rule 9 */ - val r9 = Rule.create(predANS, predQM, not(predSP)) - - // List.empty - // .prepended(r9) - // .prependedAll(r8c) - // .prepended(r8b) - // .prependedAll(r8a) - // .prependedAll(r7b) - // .prependedAll(r7a) - // .prependedAll(r6) - // .prependedAll(r5c) - // .prependedAll(r5b) - // .prependedAll(r5a) - // .prependedAll(r4c) - // .prependedAll(r4b) - // .prependedAll(r4a) - // .prepended(r3c) - // .prepended(r3b) - // .prependedAll(r3a) - // .prepended(r1) + val r9 = Rule.create(RSA.Ans, RSA.QM, not(RSA.SP)) r1 :: r3a ::: r3b :: r3c :: @@ -377,26 +329,6 @@ class FilteringProgram(query: SelectQuery, constants: List[Term]) List() } - // private def reifyTupleTableAtom( - // atom: TupleTableAtom - // ): (Option[BindAtom], List[TupleTableAtom]) = { - // if (!atom.isRDF) { - // // Compute binding atom - // val bvar = RSA.getFreshVariable() - // val name = - // Literal.create(atom.getTupleTableName.toString(), Datatype.XSD_STRING) - // val args = atom.getArguments.asScala.toList.prepended(name) - // val bind = BindAtom.create(FunctionCall.create("SKOLEM", args: _*), bvar) - // // Compute reified atom - // def reifiedIRI(i: Int) = atom.getTupleTableName.getName ++ s"_$i" - // val atoms = atom.getArguments.asScala.toList.zipWithIndex - // .map { case (t, i) => TupleTableAtom.rdf(bvar, reifiedIRI(i), t) } - // (Some(bind), atoms) - // } else { - // (None, List(atom)) - // } - // } - private def reifyAtom(atom: Atom): (Option[BindAtom], List[Atom]) = { atom match { case atom: TupleTableAtom => atom.reified diff --git a/src/main/scala/rsacomb/Main.scala b/src/main/scala/rsacomb/Main.scala index 8270205..31dd5a0 100644 --- a/src/main/scala/rsacomb/Main.scala +++ b/src/main/scala/rsacomb/Main.scala @@ -10,7 +10,7 @@ import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term} /* Local imports */ -import rsacomb.RSA._ +import util.{RDFoxHelpers, RSA} object RSAComb extends App { @@ -56,8 +56,10 @@ object RSAComb extends App { if (ontology.isRSA) { /* Load query */ - val query = RDFoxUtil.parseQuery( + val query = RDFoxHelpers.parseSelectQuery( """ + PREFIX : + SELECT ?X WHERE { ?X a :D ; @@ -71,8 +73,11 @@ object RSAComb extends App { /* Compute answers to query */ query match { case Some(query) => { + + import implicits.JavaCollections._ + // Open connection to RDFox - val (server, data) = RDFoxUtil.openConnection("AnswerComputation") + val (server, data) = RDFoxHelpers.openConnection("AnswerComputation") { println("\nQuery") @@ -81,7 +86,7 @@ object RSAComb extends App { // Step 1. Computing the canonical model val canon = ontology.canonicalModel - data.addRules(canon.rules.asJava) + data.addRules(canon.rules) { println("\nCanonical Model rules:") @@ -90,129 +95,136 @@ object RSAComb extends App { // Step 2. Computing the canonical model val nis = { - val query = - "SELECT ?Y WHERE { ?X rsa:EquivTo ?Y ; a rsa:NAMED . }" - val cursor = - data.createCursor( - RSA.Prefixes, - query, - new HashMap[String, String]() - ); - var mul = cursor.open() - var iris: List[IRI] = List() - while (mul > 0) { - println(cursor.getResource(0)) - iris = cursor.getResource(0) match { - case iri: IRI => iri :: iris - case _ => iris - } - mul = cursor.advance() - } - iris + val query = "SELECT ?Y WHERE { ?X rsa:EquivTo ?Y ; a rsa:Named . }" + RDFoxHelpers.submitSelectQuery(data, query, RSA.Prefixes).flatten } val filter = ontology.filteringProgram(query, nis) - data.addRules(filter.rules.asJava) + data.addRules(filter.rules) { println("\nFiltering rules") filter.rules.foreach(println) } - def retrieveInstances(pred: String, arity: Int): Unit = { - // Build query - var query = "SELECT" - for (i <- 0 until arity) { - query ++= s" ?X$i" - } - query ++= " WHERE {" - for (i <- 0 until arity) { - query ++= s" ?S rsa:${pred}_$i ?X$i ." - } - query ++= " }" - // Collect answers - RDFoxUtil.submitQuery( - data, - RSA.Prefixes, - query, - arity - ) - } - // Retrieve answers println("\nAnswers:") - retrieveInstances("ANS", filter.answer.length) + val ans = + RDFoxHelpers.queryInternalPredicate(data, "Ans", filter.answer.length) + println(ans) /* DEBUG: adding additional checks */ - println("\nIndividuals:") - ontology.individuals.foreach(println) - - println("\nThings:") - RDFoxUtil.submitQuery( - data, - RSA.Prefixes, - "SELECT ?X { ?X a owl:Thing }", - 1 - ) - - println("\nNAMEDs:") - RDFoxUtil.submitQuery( - data, - RSA.Prefixes, - "SELECT ?X { ?X a rsa:NAMED }", - 1 - ) - - println("\nNIs:") - RDFoxUtil.submitQuery( - data, - RSA.Prefixes, - "SELECT ?X { ?X a rsa:NI }", - 1 - ) - - // ID instances - println("\nID instances:") - retrieveInstances("ID", filter.variables.length + 2) - - println("\nSameAs instances:") - RDFoxUtil.submitQuery( - data, - RSA.Prefixes, - "SELECT ?X ?Y { ?X rsa:EquivTo ?Y }", - 2 - ) - - // Unfiltered answers - println("\nPossible answers:") - retrieveInstances("QM", filter.variables.length) - - // Cycle detected - println("\nCycle detection:") - retrieveInstances("AQ_f", filter.variables.length + 2) - retrieveInstances("AQ_b", filter.variables.length + 2) - - // Forks detected - println("\nForks:") - retrieveInstances("FK", filter.variables.length) - - // Spurious answers - println("\nSpurious answers") - retrieveInstances("SP", filter.variables.length) - { - val cursor = data.createCursor( - RSA.Prefixes, - "ASK { :a a :D }", - new HashMap[String, String]() - ); - var mul = cursor.open() - println(s"Answer: ${mul > 0}") - cursor.close(); + import suffix.{Forward, Backward} + + val arity = filter.answer.length + filter.bounded.length + + println("\nIndividuals:") + ontology.individuals.foreach(println) + + println("\nThings:") + val things = RDFoxHelpers.submitSelectQuery( + data, + """ + PREFIX owl: + + SELECT ?X { + ?X a owl:Thing + } + """ + ) + println(things) + + println("\nNAMEDs:") + val named = RDFoxHelpers.submitSelectQuery( + data, + """ + SELECT ?X { + ?X a rsa:Named + } + """, + RSA.Prefixes + ) + println(named) + + println("\nNIs:") + val nis = RDFoxHelpers.submitSelectQuery( + data, + """ + SELECT ?X { + ?X a rsa:NI + } + """, + RSA.Prefixes + ) + println(nis) + + // ID instances + println("\nIDs:") + val ids = RDFoxHelpers.queryInternalPredicate( + data, + "ID", + arity + 2 + ) + println(ids) + + println("\nEquivTo:") + val equivs = RDFoxHelpers.submitSelectQuery( + data, + """ + SELECT ?X ?Y { + ?X rsa:EquivTo ?Y + } + """, + RSA.Prefixes + ) + println(equivs) + + // Unfiltered answers + println("\nPossible answers:") + val qms = RDFoxHelpers.queryInternalPredicate( + data, + "QM", + arity + ) + println(qms) + + // Cycle detected + println("\nCycle detection:") + val aqf = RDFoxHelpers.queryInternalPredicate( + data, + "AQ" :: Forward, + arity + 2 + ) + val aqb = RDFoxHelpers.queryInternalPredicate( + data, + "AQ" :: Backward, + arity + 2 + ) + println(aqf) + println(aqb) + + // Forks detected + println("\nForks:") + val fk = RDFoxHelpers.queryInternalPredicate( + data, + "FK", + arity + ) + println(fk) + + // Spurious answers + println("\nSpurious answers") + val sp = RDFoxHelpers.queryInternalPredicate( + data, + "SP", + arity + ) + println(sp) } // Close connection to RDFox - RDFoxUtil.closeConnection(server, data) + RDFoxHelpers.closeConnection(server, data) } case None => {} } diff --git a/src/main/scala/rsacomb/RDFoxAxiomConverter.scala b/src/main/scala/rsacomb/RDFoxAxiomConverter.scala index 0368b7c..9b78e8e 100644 --- a/src/main/scala/rsacomb/RDFoxAxiomConverter.scala +++ b/src/main/scala/rsacomb/RDFoxAxiomConverter.scala @@ -78,7 +78,7 @@ class RDFoxAxiomConverter( } override def visit(axiom: OWLSubObjectPropertyOfAxiom): List[Rule] = { - val term1 = RSA.getFreshVariable() + val term1 = RSAOntology.genFreshVariable() val subVisitor = new RDFoxPropertyExprConverter(term, term1, suffix) val superVisitor = new RDFoxPropertyExprConverter(term, term1, suffix) diff --git a/src/main/scala/rsacomb/RDFoxClassExprConverter.scala b/src/main/scala/rsacomb/RDFoxClassExprConverter.scala index f3a0dfc..f4187ed 100644 --- a/src/main/scala/rsacomb/RDFoxClassExprConverter.scala +++ b/src/main/scala/rsacomb/RDFoxClassExprConverter.scala @@ -26,12 +26,11 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{ IRI } -import rsacomb.SkolemStrategy -import rsacomb.RDFoxRuleShards import org.semanticweb.owlapi.model.OWLObjectPropertyExpression import org.semanticweb.owlapi.model.OWLObjectProperty import suffix.{RSASuffix, Empty} +import util.RSA object RDFoxClassExprConverter { @@ -61,7 +60,7 @@ class RDFoxClassExprConverter( suffix: RSASuffix ) extends OWLClassExpressionVisitorEx[RDFoxRuleShards] { - import RDFoxUtil.owlapi2rdfox; + import implicits.RDFox._ // OWLClass override def visit(expr: OWLClass): RDFoxRuleShards = { @@ -99,7 +98,7 @@ class RDFoxClassExprConverter( // OWLObjectSomeValuesFrom override def visit(expr: OWLObjectSomeValuesFrom): RDFoxRuleShards = { - val y = RSA.getFreshVariable() + val y = RSAOntology.genFreshVariable() // Here we are assuming a role name val prop = expr.getProperty() // Computes the result of rule skolemization. Depending on the used @@ -110,14 +109,7 @@ class RDFoxClassExprConverter( case SkolemStrategy.Constant(c) => (List(), List(), c) case SkolemStrategy.ConstantRSA(c) => { if (unsafe.contains(prop)) - ( - List( - TupleTableAtom.rdf(term, RSA.rsa("PE"), c), - TupleTableAtom.rdf(c, IRI.RDF_TYPE, RSA.rsa("U")) - ), - List(), - c - ) + (List(RSA.PE(term, c), RSA.U(c)), List(), c) else (List(), List(), c) } @@ -143,7 +135,8 @@ class RDFoxClassExprConverter( // OWLObjectMaxCardinality override def visit(expr: OWLObjectMaxCardinality): RDFoxRuleShards = { // TODO: again, no hardcoded variables - val vars = List(RSA.getFreshVariable(), RSA.getFreshVariable()) + val vars = + List(RSAOntology.genFreshVariable(), RSAOntology.genFreshVariable()) val classResult = RDFoxClassExprConverter.merge( vars .map(new RDFoxClassExprConverter(_, unsafe, skolem, suffix)) diff --git a/src/main/scala/rsacomb/RDFoxPropertyExprConverter.scala b/src/main/scala/rsacomb/RDFoxPropertyExprConverter.scala index 525ec62..826e965 100644 --- a/src/main/scala/rsacomb/RDFoxPropertyExprConverter.scala +++ b/src/main/scala/rsacomb/RDFoxPropertyExprConverter.scala @@ -17,7 +17,7 @@ class RDFoxPropertyExprConverter( ) extends OWLPropertyExpressionVisitorEx[List[TupleTableAtom]] { // Automatically converts OWLAPI types into RDFox equivalent types. - import RDFoxUtil.owlapi2rdfox; + import implicits.RDFox._ override def visit(expr: OWLObjectProperty): List[TupleTableAtom] = { val base = expr.getIRI.getIRIString diff --git a/src/main/scala/rsacomb/RDFoxUtil.scala b/src/main/scala/rsacomb/RDFoxUtil.scala deleted file mode 100644 index 653c51f..0000000 --- a/src/main/scala/rsacomb/RDFoxUtil.scala +++ /dev/null @@ -1,113 +0,0 @@ -package rsacomb - -/* Java imports */ -import java.util.HashMap -import java.io.StringReader -import tech.oxfordsemantic.jrdfox.Prefixes -import tech.oxfordsemantic.jrdfox.logic.sparql.statement.{Query, SelectQuery} -import tech.oxfordsemantic.jrdfox.client.{ - ConnectionFactory, - ServerConnection, - DataStoreConnection -} -import tech.oxfordsemantic.jrdfox.formats.SPARQLParser - -import tech.oxfordsemantic.jrdfox.logic.expression.{IRI => RDFox_IRI} -import org.semanticweb.owlapi.model.{IRI => OWL_IRI} - -import scala.collection.JavaConverters._ - -object RDFoxUtil { - - implicit def rdfox2owlapi(iri: RDFox_IRI): OWL_IRI = { - OWL_IRI.create(iri.getIRI) - } - - implicit def owlapi2rdfox(iri: OWL_IRI): RDFox_IRI = { - RDFox_IRI.create(iri.getIRIString()) - } - - implicit def stringToRDFoxIRI(iri: String): RDFox_IRI = { - RDFox_IRI.create(iri) - } - - implicit def javaToScalaList[A](list: java.util.List[A]): List[A] = { - list.asScala.toList - } - - implicit def scalaToJavaList[A](list: List[A]): java.util.List[A] = { - list.asJava - } - - def openConnection( - dataStore: String - ): (ServerConnection, DataStoreConnection) = { - /* Create local server connection - */ - val serverUrl = "rdfox:local" - val role = "" - val password = "" - val server = - ConnectionFactory.newServerConnection(serverUrl, role, password) - - /* Create datastore connection - */ - val parameters = new HashMap[String, String]() - parameters.put("owl-in-rdf-support", "relaxed") - //parameters.put("equality", "noUNA") - server.createDataStore(dataStore, "par-complex-nn", parameters) - val data = server.newDataStoreConnection(dataStore) - - (server, data) - } - - def parseQuery( - query: String, - prefixes: Prefixes = RSA.Prefixes - ): Option[SelectQuery] = { - val parser = new SPARQLParser( - prefixes, - new StringReader(query) - ) - // NOTE: return only conjunctive queries for now (SelectQuery) - parser.parseSingleQuery() match { - case q: SelectQuery => Some(q) - case _ => None - } - } - - def submitQuery( - data: DataStoreConnection, - prefixes: Prefixes, - query: String, - answers: Int - ): Unit = { - println(s"\nQUERY {\n$query\n}") - val cursor = data.createCursor( - prefixes, - query, - new HashMap[String, String]() - ); - var mul = cursor.open() - while (mul > 0) { - print("Answer: ") - for (i <- 0 until answers) { - val res = cursor.getResource(i) - print(s"$res ") - } - println() - mul = cursor.advance() - } - cursor.close(); - println(s"QUERY END") - } - - def closeConnection( - server: ServerConnection, - data: DataStoreConnection - ): Unit = { - server.close(); - data.close(); - } - -} // object RDFoxUtil diff --git a/src/main/scala/rsacomb/RSA.scala b/src/main/scala/rsacomb/RSA.scala index b0e140b..1b2aa9c 100644 --- a/src/main/scala/rsacomb/RSA.scala +++ b/src/main/scala/rsacomb/RSA.scala @@ -1,11 +1,16 @@ -package rsacomb +package rsacomb.util /* Java imports */ import java.util.Map import tech.oxfordsemantic.jrdfox.formats.SPARQLParser import tech.oxfordsemantic.jrdfox.Prefixes -import tech.oxfordsemantic.jrdfox.logic.expression.{Variable, IRI} +import tech.oxfordsemantic.jrdfox.logic.datalog.{ + TupleTableAtom, + TupleTableName, + Negation +} +import tech.oxfordsemantic.jrdfox.logic.expression.{Term, Variable, IRI} import org.semanticweb.owlapi.model.OWLOntology import org.semanticweb.owlapi.model.{ OWLAxiom, @@ -13,51 +18,83 @@ import org.semanticweb.owlapi.model.{ OWLObjectPropertyExpression } +import rsacomb.suffix.RSASuffix + // Debug only import scala.collection.JavaConverters._ -object RSA extends RSAAxiom { +object RSA { val Prefixes: Prefixes = new Prefixes() - Prefixes.declarePrefix(":", "http://example.com/rsa_example.owl#") Prefixes.declarePrefix("rsa:", "http://127.0.0.1/") - Prefixes.declarePrefix("rdf:", "http://www.w3.org/1999/02/22-rdf-syntax-ns#") - Prefixes.declarePrefix("rdfs:", "http://www.w3.org/2000/01/rdf-schema#") - Prefixes.declarePrefix("owl:", "http://www.w3.org/2002/07/owl#") - val EquivTo: IRI = this.rsa("EquivTo") - val Named: IRI = this.rsa("NAMED") + private def atom(name: IRI, vars: List[Term]) = + TupleTableAtom.create(TupleTableName.create(name.getIRI), vars: _*) + + def PE(t1: Term, t2: Term) = + TupleTableAtom.rdf(t1, RSA("PE"), t2) + + def U(t: Term) = + TupleTableAtom.rdf(t, IRI.RDF_TYPE, RSA("U")) + + def In(t: Term)(implicit set: Term) = + TupleTableAtom.rdf(t, RSA("In"), set) + + def notIn(t: Term)(implicit set: Term) = Negation.create(In(t)(set)) - // Counter used to implement a simple fresh variable generator - private var counter = -1; + def EquivTo(t1: Term, t2: Term) = + TupleTableAtom.rdf(t1, RSA("EquivTo"), t2) - def getFreshVariable(): Variable = { - counter += 1 - Variable.create(f"I$counter%03d") + def QM(implicit variables: (List[Term], List[Term])) = { + val (answer, bounded) = variables + atom(RSA("QM"), answer ::: bounded) } - def base(name: Any): IRI = - IRI.create( - Prefixes.getPrefixIRIsByPrefixName.get(":").getIRI - + name.toString - ) + def ID(t1: Term, t2: Term)(implicit variables: (List[Term], List[Term])) = { + val (answer, bounded) = variables + atom(RSA("ID"), (answer ::: bounded) :+ t1 :+ t2) + } - def rsa(name: Any): IRI = - IRI.create( - Prefixes.getPrefixIRIsByPrefixName.get("rsa:").getIRI - + name.toString - ) + def Named(t: Term) = + TupleTableAtom.rdf(t, IRI.RDF_TYPE, RSA("Named")) + + def Thing(t: Term) = + TupleTableAtom.rdf(t, IRI.RDF_TYPE, IRI.THING) - def hashed( - cls1: OWLClass, - prop: OWLObjectPropertyExpression, - cls2: OWLClass - ): String = - (cls1, prop, cls2).hashCode.toString + def NI(t: Term) = + TupleTableAtom.rdf(t, IRI.RDF_TYPE, RSA("NI")) - def hashed(axiom: OWLAxiom): String = { - val (cls1, prop, cls2) = axiom.toTriple.get - this.hashed(cls1, prop, cls2) + def TQ(t1: Term, t2: Term, sx: RSASuffix)(implicit + variables: (List[Term], List[Term]) + ) = { + val (answer, bounded) = variables + atom(RSA("TQ" :: sx), (answer ::: bounded) :+ t1 :+ t2) } -} // object RSA + def AQ(t1: Term, t2: Term, sx: RSASuffix)(implicit + variables: (List[Term], List[Term]) + ) = { + val (answer, bounded) = variables + atom(RSA("AQ" :: sx), (answer ::: bounded) :+ t1 :+ t2) + } + + def FK(implicit variables: (List[Term], List[Term])) = { + val (answer, bounded) = variables + atom(RSA("FK"), answer ::: bounded) + } + + def SP(implicit variables: (List[Term], List[Term])) = { + val (answer, bounded) = variables + atom(RSA("SP"), answer ::: bounded) + } + + def Ans(implicit variables: (List[Term], List[Term])) = { + val (answer, _) = variables + atom(RSA("Ans"), answer) + } + + def apply(name: Any): IRI = + IRI.create( + Prefixes.getPrefixIRIsByPrefixName.get("rsa:").getIRI + name.toString + ) +} diff --git a/src/main/scala/rsacomb/RSAAtom.scala b/src/main/scala/rsacomb/RSAAtom.scala index a65c168..8832226 100644 --- a/src/main/scala/rsacomb/RSAAtom.scala +++ b/src/main/scala/rsacomb/RSAAtom.scala @@ -11,7 +11,7 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{IRI} import scala.collection.JavaConverters._ import rsacomb.suffix.{RSASuffix, Nth} -import rsacomb.RSA +import rsacomb.RSAOntology /* Is this the best way to determine if an atom is an RDF triple? * Note that we can't use `getNumberOfArguments()` because is not @@ -32,7 +32,7 @@ trait RSAAtom { implicit class RSAAtom(val atom: TupleTableAtom) { - import rsacomb.RDFoxUtil.stringToRDFoxIRI + import RDFox._ val name: String = atom.getTupleTableName.getName @@ -74,7 +74,7 @@ trait RSAAtom { if (isRDF) { (None, List(atom)) } else { - val bvar = RSA.getFreshVariable() + val bvar = RSAOntology.genFreshVariable() val str = Literal.create(name, Datatype.XSD_STRING) val args = atom.getArguments.asScala.toList val skolem = FunctionCall.create("SKOLEM", str :: args: _*) diff --git a/src/main/scala/rsacomb/RSAAxiom.scala b/src/main/scala/rsacomb/RSAAxiom.scala index 3cd9a9d..08de5b7 100644 --- a/src/main/scala/rsacomb/RSAAxiom.scala +++ b/src/main/scala/rsacomb/RSAAxiom.scala @@ -38,6 +38,17 @@ trait RSAAxiom { case object T5 extends RSAAxiomType // A ⊑ ∃R.B } + object RSAAxiom { + + def hashed( + cls1: OWLClass, + prop: OWLObjectPropertyExpression, + cls2: OWLClass + ): String = + (cls1, prop, cls2).hashCode.toString + + } + /* Implements additional features on top of `OWLAxiom` from * the OWLAPI. */ @@ -137,6 +148,8 @@ trait RSAAxiom { } cls2 <- Some(someValues.getFiller) collect { case a: OWLClass => a } } yield (cls1, prop, cls2) + + lazy val hashed: String = (RSAAxiom.hashed _) tupled toTriple.get } } // trait RSAAxiom diff --git a/src/main/scala/rsacomb/RSAOntology.scala b/src/main/scala/rsacomb/RSAOntology.scala index 52bff37..1a5e4ca 100644 --- a/src/main/scala/rsacomb/RSAOntology.scala +++ b/src/main/scala/rsacomb/RSAOntology.scala @@ -47,14 +47,23 @@ import tech.oxfordsemantic.jrdfox.logic._ import org.semanticweb.owlapi.model.OWLObjectInverseOf import suffix.{Empty, Forward, Backward, Inverse} +import util.{RDFoxHelpers, RSA} object RSAOntology { + // Counter used to implement a simple fresh variable generator + private var counter = -1; + def apply(ontology: OWLOntology): RSAOntology = new RSAOntology(ontology) def apply(ontology: File): RSAOntology = new RSAOntology(loadOntology(ontology)) + def genFreshVariable(): Variable = { + counter += 1 + Variable.create(f"I$counter%03d") + } + private def loadOntology(onto: File): OWLOntology = { val manager = OWLManager.createOWLOntologyManager() manager.loadOntologyFromOntologyDocument(onto) @@ -94,7 +103,7 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom { .getIndividualsInSignature() .asScala .map(_.getIRI) - .map(RDFoxUtil.owlapi2rdfox) + .map(implicits.RDFox.owlapiToRdfoxIri) .toList val concepts: List[OWLClass] = @@ -133,7 +142,7 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom { val datalog = for { axiom <- axioms visitor = new RDFoxAxiomConverter( - RSA.getFreshVariable(), + RSAOntology.genFreshVariable(), unsafe, SkolemStrategy.ConstantRSA(axiom.toString), Empty @@ -146,9 +155,9 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom { //datalog.foreach(println) // Open connection with RDFox - val (server, data) = RDFoxUtil.openConnection("RSACheck") + val (server, data) = RDFoxHelpers.openConnection("RSACheck") // Add Data (hardcoded for now) - data.importData(UpdateType.ADDITION, RSA.Prefixes, ":a a :A .") + //data.importData(UpdateType.ADDITION, RSA.Prefixes, ":a a :A .") /* Add built-in rules */ @@ -176,7 +185,7 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom { //println(graph) // Close connection to RDFox - RDFoxUtil.closeConnection(server, data) + RDFoxHelpers.closeConnection(server, data) /* To check if the graph is tree-like we check for acyclicity in a * undirected graph. @@ -291,8 +300,8 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom { val role = axiom.objectPropertyExpressionsInSignature(0) if (this.confl(role).contains(role)) { Set( - RSA.rsa("v0_" ++ RSA.hashed(axiom)), - RSA.rsa("v1_" ++ RSA.hashed(axiom)) + RSA("v0_" ++ axiom.hashed), + RSA("v1_" ++ axiom.hashed) ) } else { Set() @@ -354,15 +363,15 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom { classC <- classes // Keeping this check for now if !unsafeRoles.contains(roleS) - tripleARB = RSA.hashed(classA, roleR, classB) - tripleDSC = RSA.hashed(classD, roleS, classC) + tripleARB = RSAAxiom.hashed(classA, roleR, classB) + tripleDSC = RSAAxiom.hashed(classD, roleS, classC) individual = if (tripleARB > tripleDSC) { - RSA.rsa("v1_" ++ tripleDSC) + RSA("v1_" ++ tripleDSC) } else { // Note that this is also the case for // `tripleARB == tripleDSC` - RSA.rsa("v0_" ++ tripleDSC) + RSA("v0_" ++ tripleDSC) } } yield individual } diff --git a/src/main/scala/rsacomb/implicits/JavaCollections.scala b/src/main/scala/rsacomb/implicits/JavaCollections.scala new file mode 100644 index 0000000..69e825b --- /dev/null +++ b/src/main/scala/rsacomb/implicits/JavaCollections.scala @@ -0,0 +1,13 @@ +package rsacomb.implicits + +import scala.collection.JavaConverters._ + +object JavaCollections { + + implicit def javaToScalaList[A](list: java.util.List[A]): List[A] = + list.asScala.toList + + implicit def scalaToJavaList[A](list: List[A]): java.util.List[A] = + list.asJava + +} diff --git a/src/main/scala/rsacomb/implicits/RDFox.scala b/src/main/scala/rsacomb/implicits/RDFox.scala new file mode 100644 index 0000000..44b7c01 --- /dev/null +++ b/src/main/scala/rsacomb/implicits/RDFox.scala @@ -0,0 +1,20 @@ +package rsacomb.implicits + +import tech.oxfordsemantic.jrdfox.logic.expression.{IRI => RDFoxIRI} +import org.semanticweb.owlapi.model.{IRI => OWLIRI} + +object RDFox { + + implicit def rdfoxToOwlapiIri(iri: RDFoxIRI): OWLIRI = { + OWLIRI.create(iri.getIRI) + } + + implicit def owlapiToRdfoxIri(iri: OWLIRI): RDFoxIRI = { + RDFoxIRI.create(iri.getIRIString()) + } + + implicit def stringToRdfoxIri(iri: String): RDFoxIRI = { + RDFoxIRI.create(iri) + } + +} diff --git a/src/main/scala/rsacomb/util/RDFoxHelpers.scala b/src/main/scala/rsacomb/util/RDFoxHelpers.scala new file mode 100644 index 0000000..9856e27 --- /dev/null +++ b/src/main/scala/rsacomb/util/RDFoxHelpers.scala @@ -0,0 +1,100 @@ +package rsacomb.util + +import java.util.{Map => JMap, HashMap => JHashMap} +import java.io.StringReader +import tech.oxfordsemantic.jrdfox.Prefixes +import tech.oxfordsemantic.jrdfox.client.{ + ConnectionFactory, + ServerConnection, + DataStoreConnection +} +import tech.oxfordsemantic.jrdfox.formats.SPARQLParser +import tech.oxfordsemantic.jrdfox.logic.expression.Resource +import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery + +import rsacomb.suffix.Nth + +object RDFoxHelpers { + + def openConnection( + dataStore: String, + opts: JMap[String, String] = new JHashMap[String, String]() + ): (ServerConnection, DataStoreConnection) = { + /* Create local server connection + */ + val serverUrl = "rdfox:local" + val role = "" + val password = "" + val server = + ConnectionFactory.newServerConnection(serverUrl, role, password) + + /* Create datastore connection + */ + // parameters.put("owl-in-rdf-support", "relaxed") + // parameters.put("equality", "noUNA") + server.createDataStore(dataStore, "par-complex-nn", opts) + val data = server.newDataStoreConnection(dataStore) + + (server, data) + } + + def parseSelectQuery( + query: String, + prefixes: Prefixes = new Prefixes() + ): Option[SelectQuery] = { + val parser = new SPARQLParser( + prefixes, + new StringReader(query) + ) + parser.parseSingleQuery() match { + case q: SelectQuery => Some(q) + case _ => None + } + } + + def submitSelectQuery( + data: DataStoreConnection, + query: String, + prefixes: Prefixes = new Prefixes(), + opts: JMap[String, String] = new JHashMap[String, String]() + ): List[List[Resource]] = { + val cursor = data.createCursor(prefixes, query, opts) + var answers: List[List[Resource]] = List() + var mul = cursor.open() + while (mul > 0) { + val answer = + (0 until cursor.getArity).map(cursor.getResource(_)).toList + answers = answer :: answers + mul = cursor.advance() + } + cursor.close(); + answers + } + + def queryInternalPredicate( + data: DataStoreConnection, + pred: String, + arity: Int, + opts: JMap[String, String] = new JHashMap[String, String]() + ): List[List[Resource]] = { + var query = "SELECT" + for (i <- 0 until arity) { + query ++= s" ?X$i" + } + query ++= " WHERE {" + for (i <- 0 until arity) { + query ++= s" ?S rsa:${pred :: Nth(i)} ?X$i ." + } + query ++= " }" + submitSelectQuery(data, query, RSA.Prefixes, opts) + } + + def closeConnection( + server: ServerConnection, + data: DataStoreConnection + ): Unit = { + server.close(); + data.close(); + } + +} -- cgit v1.2.3