diff options
| author | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-12-07 13:54:37 +0000 |
|---|---|---|
| committer | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-12-07 13:54:37 +0000 |
| commit | 333e4f36e787f93c4c9547b17004da1574b5f991 (patch) | |
| tree | decd27e9efcc3bef981402be681ab727539f99be /src | |
| parent | bbbb61ee13fa258cbed0b502426534afad49b651 (diff) | |
| download | RSAComb-333e4f36e787f93c4c9547b17004da1574b5f991.tar.gz RSAComb-333e4f36e787f93c4c9547b17004da1574b5f991.zip | |
Add first implementation of a logger
This is needed mostly for debugging and benchmarking purposes. We tried
to make it as "out of the way" as possible.
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala | 16 | ||||
| -rw-r--r-- | src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala | 230 | ||||
| -rw-r--r-- | src/main/scala/uk/ac/ox/cs/rsacomb/util/Logger.scala | 45 | ||||
| -rw-r--r-- | src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala | 68 |
4 files changed, 230 insertions, 129 deletions
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala index d41ca8c..5246d2f 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala | |||
| @@ -10,7 +10,7 @@ import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery | |||
| 10 | import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term} | 10 | import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term} |
| 11 | 11 | ||
| 12 | /* Local imports */ | 12 | /* Local imports */ |
| 13 | import util.{RDFoxUtil, RSA} | 13 | import util.{Logger, RDFoxUtil, RSA} |
| 14 | import sparql.ConjunctiveQuery | 14 | import sparql.ConjunctiveQuery |
| 15 | 15 | ||
| 16 | object RSAComb extends App { | 16 | object RSAComb extends App { |
| @@ -53,15 +53,17 @@ object RSAComb extends App { | |||
| 53 | 53 | ||
| 54 | val ontology = RSAOntology(ontoPaths: _*) | 54 | val ontology = RSAOntology(ontoPaths: _*) |
| 55 | if (ontology.isRSA) { | 55 | if (ontology.isRSA) { |
| 56 | //println("ONTOLOGY IS RSA") | 56 | |
| 57 | Logger print "Ontology is RSA!" | ||
| 57 | 58 | ||
| 58 | /** Read SPARQL query from file */ | 59 | /** Read SPARQL query from file */ |
| 59 | val source = io.Source.fromFile(queryPath.getAbsoluteFile) | 60 | val query = RDFoxUtil.loadQueryFromFile(queryPath.getAbsoluteFile) |
| 60 | val query = source.getLines mkString "\n" | ||
| 61 | source.close() | ||
| 62 | 61 | ||
| 63 | /* Compute answers to query */ | 62 | /* Compute answers to query */ |
| 64 | val answers = ConjunctiveQuery(query).map(ontology ask _) | 63 | ConjunctiveQuery(query).map(ontology ask _) match { |
| 65 | answers map (_.toString) foreach println | 64 | case Some(answers) => Logger print answers |
| 65 | case None => | ||
| 66 | throw new RuntimeException("Submitted query is not conjunctive") | ||
| 67 | } | ||
| 66 | } | 68 | } |
| 67 | } | 69 | } |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala index 52d4905..87a2312 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala | |||
| @@ -54,6 +54,7 @@ import uk.ac.ox.cs.rsacomb.converter._ | |||
| 54 | import uk.ac.ox.cs.rsacomb.suffix._ | 54 | import uk.ac.ox.cs.rsacomb.suffix._ |
| 55 | import uk.ac.ox.cs.rsacomb.sparql._ | 55 | import uk.ac.ox.cs.rsacomb.sparql._ |
| 56 | import uk.ac.ox.cs.rsacomb.util.{RDFoxUtil, RSA} | 56 | import uk.ac.ox.cs.rsacomb.util.{RDFoxUtil, RSA} |
| 57 | import uk.ac.ox.cs.rsacomb.util.Logger | ||
| 57 | 58 | ||
| 58 | object RSAOntology { | 59 | object RSAOntology { |
| 59 | 60 | ||
| @@ -141,87 +142,91 @@ class RSAOntology(val ontology: OWLOntology) { | |||
| 141 | * why the ontology might not be RSA. This could help a second | 142 | * why the ontology might not be RSA. This could help a second |
| 142 | * step of approximation of an Horn-ALCHOIQ to RSA | 143 | * step of approximation of an Horn-ALCHOIQ to RSA |
| 143 | */ | 144 | */ |
| 144 | lazy val isRSA: Boolean = { | 145 | lazy val isRSA: Boolean = Logger.timed( |
| 145 | 146 | { | |
| 146 | val unsafe = this.unsafeRoles | 147 | val unsafe = this.unsafeRoles |
| 147 | 148 | ||
| 148 | /* DEBUG: print rules in DL syntax and unsafe roles */ | 149 | // val renderer = new DLSyntaxObjectRenderer() |
| 149 | //val renderer = new DLSyntaxObjectRenderer() | 150 | // println() |
| 150 | //println("\nDL rules:") | 151 | // println("Unsafe roles:") |
| 151 | //axioms.foreach(x => println(renderer.render(x))) | 152 | // println(unsafe) |
| 152 | //println("\nUnsafe roles:") | 153 | // println() |
| 153 | //println(unsafe) | 154 | // println("DL rules:") |
| 154 | 155 | // tbox.foreach(x => println(renderer.render(x))) | |
| 155 | object RSAConverter extends RDFoxConverter { | 156 | |
| 156 | 157 | object RSAConverter extends RDFoxConverter { | |
| 157 | override def convert( | 158 | |
| 158 | expr: OWLClassExpression, | 159 | override def convert( |
| 159 | term: Term, | 160 | expr: OWLClassExpression, |
| 160 | unsafe: List[OWLObjectPropertyExpression], | 161 | term: Term, |
| 161 | skolem: SkolemStrategy, | 162 | unsafe: List[OWLObjectPropertyExpression], |
| 162 | suffix: RSASuffix | 163 | skolem: SkolemStrategy, |
| 163 | ): Shards = | 164 | suffix: RSASuffix |
| 164 | (expr, skolem) match { | 165 | ): Shards = |
| 165 | 166 | (expr, skolem) match { | |
| 166 | case (e: OWLObjectSomeValuesFrom, c: Constant) | 167 | |
| 167 | if unsafe contains e.getProperty => { | 168 | case (e: OWLObjectSomeValuesFrom, c: Constant) |
| 168 | val (res, ext) = super.convert(e, term, unsafe, skolem, suffix) | 169 | if unsafe contains e.getProperty => { |
| 169 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) | 170 | val (res, ext) = super.convert(e, term, unsafe, skolem, suffix) |
| 170 | } | 171 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) |
| 171 | 172 | } | |
| 172 | case (e: OWLDataSomeValuesFrom, c: Constant) | 173 | |
| 173 | if unsafe contains e.getProperty => { | 174 | case (e: OWLDataSomeValuesFrom, c: Constant) |
| 174 | val (res, ext) = super.convert(e, term, unsafe, skolem, suffix) | 175 | if unsafe contains e.getProperty => { |
| 175 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) | 176 | val (res, ext) = super.convert(e, term, unsafe, skolem, suffix) |
| 177 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) | ||
| 178 | } | ||
| 179 | |||
| 180 | case _ => super.convert(expr, term, unsafe, skolem, suffix) | ||
| 176 | } | 181 | } |
| 177 | 182 | ||
| 178 | case _ => super.convert(expr, term, unsafe, skolem, suffix) | 183 | } |
| 179 | } | 184 | |
| 180 | 185 | /* Ontology convertion into LP rules */ | |
| 181 | } | 186 | val term = RSAOntology.genFreshVariable() |
| 182 | 187 | val datalog = axioms | |
| 183 | /* Ontology convertion into LP rules */ | 188 | .map(a => RSAConverter.convert(a, term, unsafe, new Constant(a), Empty)) |
| 184 | val term = RSAOntology.genFreshVariable() | 189 | .unzip |
| 185 | val datalog = axioms | 190 | val facts = datalog._1.flatten |
| 186 | .map(a => RSAConverter.convert(a, term, unsafe, new Constant(a), Empty)) | 191 | val rules = datalog._2.flatten |
| 187 | .unzip | 192 | |
| 188 | val facts = datalog._1.flatten | 193 | //println("Datalog rules:") |
| 189 | val rules = datalog._2.flatten | 194 | //rules foreach println |
| 190 | 195 | ||
| 191 | /* DEBUG: print datalog rules */ | 196 | // Open connection with RDFox |
| 192 | //println("\nDatalog rules:") | 197 | val (server, data) = RDFoxUtil.openConnection("RSACheck") |
| 193 | //rules.foreach(println) | 198 | |
| 194 | 199 | /* Add built-in rules | |
| 195 | // Open connection with RDFox | 200 | * TODO: substitute with RDFoxUtil.addRules |
| 196 | val (server, data) = RDFoxUtil.openConnection("RSACheck") | 201 | */ |
| 197 | 202 | data.importData( | |
| 198 | /* Add built-in rules | 203 | UpdateType.ADDITION, |
| 199 | * TODO: substitute with RDFoxUtil.addRules | 204 | RSA.Prefixes, |
| 200 | */ | 205 | "rsa:E[?X,?Y] :- rsa:PE[?X,?Y], rsa:U[?X], rsa:U[?Y] ." |
| 201 | data.importData( | 206 | ) |
| 202 | UpdateType.ADDITION, | ||
| 203 | RSA.Prefixes, | ||
| 204 | "rsa:E[?X,?Y] :- rsa:PE[?X,?Y], rsa:U[?X], rsa:U[?Y] ." | ||
| 205 | ) | ||
| 206 | |||
| 207 | /* Add ontology facts and rules */ | ||
| 208 | RDFoxUtil.addFacts(data, facts) | ||
| 209 | RDFoxUtil.addRules(data, rules) | ||
| 210 | |||
| 211 | /* Build graph */ | ||
| 212 | val graph = this.rsaGraph(data); | ||
| 213 | //println(graph) | ||
| 214 | |||
| 215 | // Close connection to RDFox | ||
| 216 | RDFoxUtil.closeConnection(server, data) | ||
| 217 | 207 | ||
| 218 | /* To check if the graph is tree-like we check for acyclicity in a | 208 | /* Add ontology facts and rules */ |
| 219 | * undirected graph. | 209 | RDFoxUtil.addFacts(data, facts) |
| 220 | * | 210 | RDFoxUtil.addRules(data, rules) |
| 221 | * TODO: Implement additional checks (taking into account equality) | 211 | |
| 222 | */ | 212 | /* Build graph */ |
| 223 | graph.isAcyclic | 213 | val graph = this.rsaGraph(data); |
| 224 | } | 214 | //println("Graph:") |
| 215 | //println(graph) | ||
| 216 | |||
| 217 | // Close connection to RDFox | ||
| 218 | RDFoxUtil.closeConnection(server, data) | ||
| 219 | |||
| 220 | /* To check if the graph is tree-like we check for acyclicity in a | ||
| 221 | * undirected graph. | ||
| 222 | * | ||
| 223 | * TODO: Implement additional checks (taking into account equality) | ||
| 224 | */ | ||
| 225 | graph.isAcyclic | ||
| 226 | }, | ||
| 227 | "RSA check", | ||
| 228 | Logger.DEBUG | ||
| 229 | ) | ||
| 225 | 230 | ||
| 226 | lazy val unsafeRoles: List[OWLObjectPropertyExpression] = { | 231 | lazy val unsafeRoles: List[OWLObjectPropertyExpression] = { |
| 227 | 232 | ||
| @@ -288,9 +293,17 @@ class RSAOntology(val ontology: OWLOntology) { | |||
| 288 | } | 293 | } |
| 289 | 294 | ||
| 290 | def filteringProgram(query: ConjunctiveQuery): FilteringProgram = | 295 | def filteringProgram(query: ConjunctiveQuery): FilteringProgram = |
| 291 | new FilteringProgram(query, individuals) | 296 | Logger.timed( |
| 297 | new FilteringProgram(query, individuals), | ||
| 298 | "Generating filtering program", | ||
| 299 | Logger.DEBUG | ||
| 300 | ) | ||
| 292 | 301 | ||
| 293 | lazy val canonicalModel = new CanonicalModel(this) | 302 | lazy val canonicalModel = Logger.timed( |
| 303 | new CanonicalModel(this), | ||
| 304 | "Generating canonical model program", | ||
| 305 | Logger.DEBUG | ||
| 306 | ) | ||
| 294 | 307 | ||
| 295 | // TODO: the following functions needs testing | 308 | // TODO: the following functions needs testing |
| 296 | def confl( | 309 | def confl( |
| @@ -321,27 +334,42 @@ class RSAOntology(val ontology: OWLOntology) { | |||
| 321 | * @param query query to execute | 334 | * @param query query to execute |
| 322 | * @return a collection of answers | 335 | * @return a collection of answers |
| 323 | */ | 336 | */ |
| 324 | def ask(query: ConjunctiveQuery): ConjunctiveQueryAnswers = { | 337 | def ask(query: ConjunctiveQuery): ConjunctiveQueryAnswers = Logger.timed( |
| 325 | import implicits.JavaCollections._ | 338 | { |
| 326 | val (server, data) = RDFoxUtil.openConnection(RSAOntology.DataStore) | 339 | import implicits.JavaCollections._ |
| 327 | val filter = this.filteringProgram(query) | 340 | val (server, data) = RDFoxUtil.openConnection(RSAOntology.DataStore) |
| 328 | RDFoxUtil.addRules(data, this.canonicalModel.rules) | 341 | val canon = this.canonicalModel |
| 329 | RDFoxUtil.addFacts(data, this.canonicalModel.facts) | 342 | val filter = this.filteringProgram(query) |
| 330 | RDFoxUtil.addRules(data, filter.rules) | 343 | |
| 331 | RDFoxUtil.addFacts(data, filter.facts) | 344 | Logger print s"Canonical model: ${canon.rules.length} rules" |
| 332 | val answers = RDFoxUtil | 345 | RDFoxUtil.addRules(data, this.canonicalModel.rules) |
| 333 | .submitQuery( | 346 | |
| 334 | data, | 347 | Logger print s"Canonical model: ${canon.facts.length} facts" |
| 335 | RDFoxUtil.buildDescriptionQuery("Ans", query.answer.size), | 348 | RDFoxUtil.addFacts(data, this.canonicalModel.facts) |
| 336 | RSA.Prefixes | 349 | |
| 337 | ) | 350 | RDFoxUtil printStatisticsFor data |
| 338 | .map( | 351 | |
| 339 | new ConjunctiveQueryAnswers(query.bcq, _) | 352 | Logger print s"Filtering program: ${filter.rules.length} rules" |
| 340 | ) | 353 | RDFoxUtil.addRules(data, filter.rules) |
| 341 | .get | 354 | |
| 342 | RDFoxUtil.closeConnection(server, data) | 355 | Logger print s"Filtering program: ${filter.facts.length} facts" |
| 343 | answers | 356 | RDFoxUtil.addFacts(data, filter.facts) |
| 344 | } | 357 | |
| 358 | RDFoxUtil printStatistics data | ||
| 359 | |||
| 360 | val answers = { | ||
| 361 | val ans = RDFoxUtil.buildDescriptionQuery("Ans", query.answer.size) | ||
| 362 | RDFoxUtil | ||
| 363 | .submitQuery(data, ans, RSA.Prefixes) | ||
| 364 | .map(new ConjunctiveQueryAnswers(query.bcq, query.variables, _)) | ||
| 365 | .get | ||
| 366 | } | ||
| 367 | RDFoxUtil.closeConnection(server, data) | ||
| 368 | answers | ||
| 369 | }, | ||
| 370 | "Answers computation", | ||
| 371 | Logger.DEBUG | ||
| 372 | ) | ||
| 345 | 373 | ||
| 346 | /** Query the RDFox data store used for query answering. | 374 | /** Query the RDFox data store used for query answering. |
| 347 | * | 375 | * |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/util/Logger.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/util/Logger.scala new file mode 100644 index 0000000..74797a2 --- /dev/null +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/util/Logger.scala | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | package uk.ac.ox.cs.rsacomb.util | ||
| 2 | |||
| 3 | import java.util.Calendar | ||
| 4 | import java.io.PrintStream | ||
| 5 | |||
| 6 | /** Rough implementation of a logger. | ||
| 7 | * | ||
| 8 | * This is a WIP class for debugging and benchmarking. | ||
| 9 | */ | ||
| 10 | object Logger { | ||
| 11 | |||
| 12 | /** Output stream for the logger. */ | ||
| 13 | var output: PrintStream = System.out | ||
| 14 | |||
| 15 | /** Logger levels (i.e., verbosity of output) */ | ||
| 16 | sealed abstract class Level(val level: Int, val name: String) | ||
| 17 | extends Ordered[Level] { | ||
| 18 | def compare(that: Level) = this.level - that.level | ||
| 19 | override def toString = name | ||
| 20 | } | ||
| 21 | case object QUIET extends Level(0, "normal") | ||
| 22 | case object NORMAL extends Level(1, "normal") | ||
| 23 | case object DEBUG extends Level(2, "debug") | ||
| 24 | case object VERBOSE extends Level(3, "verbose") | ||
| 25 | |||
| 26 | /** Currend logger level */ | ||
| 27 | var level: Level = DEBUG | ||
| 28 | |||
| 29 | def print(str: Any, lvl: Level = NORMAL): Unit = { | ||
| 30 | if (lvl <= level) { | ||
| 31 | val time = Calendar.getInstance.getTime | ||
| 32 | output println s"[$lvl][$time] $str" | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | def timed[A](expr: => A, desc: String = "", lvl: Level = NORMAL): A = { | ||
| 37 | val t0 = System.currentTimeMillis() | ||
| 38 | print(s"$desc (START)", lvl) | ||
| 39 | val result = expr | ||
| 40 | val t1 = System.currentTimeMillis() | ||
| 41 | print(s"$desc (END): ${(t1 - t0).toFloat / 1000}s", lvl) | ||
| 42 | result | ||
| 43 | } | ||
| 44 | |||
| 45 | } | ||
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala index 9dd52cf..51ef903 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | package uk.ac.ox.cs.rsacomb.util | 1 | package uk.ac.ox.cs.rsacomb.util |
| 2 | 2 | ||
| 3 | import java.io.File | ||
| 3 | import java.io.StringReader | 4 | import java.io.StringReader |
| 4 | import tech.oxfordsemantic.jrdfox.Prefixes | 5 | import tech.oxfordsemantic.jrdfox.Prefixes |
| 5 | import tech.oxfordsemantic.jrdfox.client.{ | 6 | import tech.oxfordsemantic.jrdfox.client.{ |
| @@ -20,6 +21,7 @@ import tech.oxfordsemantic.jrdfox.logic.datalog.{ | |||
| 20 | import tech.oxfordsemantic.jrdfox.logic.expression.{Resource} | 21 | import tech.oxfordsemantic.jrdfox.logic.expression.{Resource} |
| 21 | import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery | 22 | import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery |
| 22 | import uk.ac.ox.cs.rsacomb.suffix.Nth | 23 | import uk.ac.ox.cs.rsacomb.suffix.Nth |
| 24 | import uk.ac.ox.cs.rsacomb.util.Logger | ||
| 23 | 25 | ||
| 24 | /** A collection of helper methods for RDFox */ | 26 | /** A collection of helper methods for RDFox */ |
| 25 | object RDFoxUtil { | 27 | object RDFoxUtil { |
| @@ -67,18 +69,21 @@ object RDFoxUtil { | |||
| 67 | (server, data) | 69 | (server, data) |
| 68 | } | 70 | } |
| 69 | 71 | ||
| 70 | /** Gather statistics from RDFox datastore. | 72 | /** Prints statistics from RDFox datastore. |
| 73 | * | ||
| 74 | * Prints something only when Logger level is set to DEBUG or more. | ||
| 71 | * | 75 | * |
| 72 | * @see [[https://docs.oxfordsemantic.tech/programmatic-access-APIs.html#in-depth-diagnostic-information]] | 76 | * @see [[https://docs.oxfordsemantic.tech/programmatic-access-APIs.html#in-depth-diagnostic-information]] |
| 73 | * and [[https://docs.oxfordsemantic.tech/programmatic-access-APIs.html#managing-statistics]] | 77 | * and [[https://docs.oxfordsemantic.tech/programmatic-access-APIs.html#managing-statistics]] |
| 74 | * for more ways of gathering diagnostics from RDFox. | 78 | * for more ways of gathering diagnostics from RDFox. |
| 75 | */ | 79 | */ |
| 76 | def gatherStatistics(data: DataStoreConnection): String = { | 80 | def printStatisticsFor(data: DataStoreConnection): Unit = { |
| 77 | val info = data.getComponentInfo(true) | 81 | val info = data.getComponentInfo(true) |
| 78 | s"${info.getName}: ${info.getPropertyValues}" | 82 | val stats = s"${info.getName}: ${info.getPropertyValues}" |
| 79 | .replaceAll("\\{", "{\n ") | 83 | .replaceAll("\\{", "{\n ") |
| 80 | .replaceAll(", ", ",\n ") | 84 | .replaceAll(", ", ",\n ") |
| 81 | .replaceAll("\\}", "\n}") | 85 | .replaceAll("\\}", "\n}") |
| 86 | Logger.print(stats, Logger.DEBUG) | ||
| 82 | } | 87 | } |
| 83 | 88 | ||
| 84 | /** Adds a collection of rules to a data store. | 89 | /** Adds a collection of rules to a data store. |
| @@ -87,7 +92,11 @@ object RDFoxUtil { | |||
| 87 | * @param rules collection of rules to be added to the data store | 92 | * @param rules collection of rules to be added to the data store |
| 88 | */ | 93 | */ |
| 89 | def addRules(data: DataStoreConnection, rules: Seq[Rule]): Unit = | 94 | def addRules(data: DataStoreConnection, rules: Seq[Rule]): Unit = |
| 90 | data addRules rules | 95 | Logger.timed( |
| 96 | data addRules rules, | ||
| 97 | "Loading rules", | ||
| 98 | Logger.DEBUG | ||
| 99 | ) | ||
| 91 | 100 | ||
| 92 | /** Adds a collection of facts to a data store. | 101 | /** Adds a collection of facts to a data store. |
| 93 | * | 102 | * |
| @@ -95,12 +104,25 @@ object RDFoxUtil { | |||
| 95 | * @param facts collection of facts to be added to the data store | 104 | * @param facts collection of facts to be added to the data store |
| 96 | */ | 105 | */ |
| 97 | def addFacts(data: DataStoreConnection, facts: Seq[TupleTableAtom]): Unit = | 106 | def addFacts(data: DataStoreConnection, facts: Seq[TupleTableAtom]): Unit = |
| 98 | data.importData( | 107 | Logger.timed( |
| 99 | UpdateType.ADDITION, | 108 | data.importData( |
| 100 | RSA.Prefixes, | 109 | UpdateType.ADDITION, |
| 101 | facts.map(_.toString(Prefixes.s_emptyPrefixes)).mkString("", ".\n", ".") | 110 | RSA.Prefixes, |
| 111 | facts.map(_.toString(Prefixes.s_emptyPrefixes)).mkString("", ".\n", ".") | ||
| 112 | ), | ||
| 113 | "Loading facts", | ||
| 114 | Logger.DEBUG | ||
| 102 | ) | 115 | ) |
| 103 | 116 | ||
| 117 | /** Load SPARQL query from file. */ | ||
| 118 | def loadQueryFromFile(file: File): String = { | ||
| 119 | val source = io.Source.fromFile(file) | ||
| 120 | val query = source.getLines mkString "\n" | ||
| 121 | Logger print s"Loaded query:\n$query" | ||
| 122 | source.close() | ||
| 123 | query | ||
| 124 | } | ||
| 125 | |||
| 104 | /** Parse a SELECT query from a string in SPARQL format. | 126 | /** Parse a SELECT query from a string in SPARQL format. |
| 105 | * | 127 | * |
| 106 | * @param query the string containing the SPARQL query | 128 | * @param query the string containing the SPARQL query |
| @@ -136,19 +158,23 @@ object RDFoxUtil { | |||
| 136 | data: DataStoreConnection, | 158 | data: DataStoreConnection, |
| 137 | query: SelectQuery, | 159 | query: SelectQuery, |
| 138 | opts: RDFoxOpts = RDFoxOpts() | 160 | opts: RDFoxOpts = RDFoxOpts() |
| 139 | ): QueryAnswers = { | 161 | ): QueryAnswers = Logger.timed( |
| 140 | val cursor = data.createCursor(query, opts) | 162 | { |
| 141 | var answers = QueryAnswers() | 163 | val cursor = data.createCursor(query, opts) |
| 142 | var mul = cursor.open() | 164 | var answers = QueryAnswers() |
| 143 | while (mul > 0) { | 165 | var mul = cursor.open() |
| 144 | val answer = | 166 | while (mul > 0) { |
| 145 | (0 until cursor.getArity).map(cursor.getResource(_)).toList | 167 | val answer = |
| 146 | answers = answer :: answers | 168 | (0 until cursor.getArity).map(cursor.getResource(_)).toList |
| 147 | mul = cursor.advance() | 169 | answers = answer :: answers |
| 148 | } | 170 | mul = cursor.advance() |
| 149 | cursor.close(); | 171 | } |
| 150 | answers | 172 | cursor.close(); |
| 151 | } | 173 | answers |
| 174 | }, | ||
| 175 | "Answer query", | ||
| 176 | Logger.DEBUG | ||
| 177 | ) | ||
| 152 | 178 | ||
| 153 | /** Execute a query over a given datastore connection. | 179 | /** Execute a query over a given datastore connection. |
| 154 | * | 180 | * |
