From 98312cd3c355a2b036edf5236dfcba755da9a17a Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Mon, 9 May 2022 12:30:20 +0100 Subject: Refactor code --- src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala | 43 ++++------ src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala | 98 +++++++++++++++------- 2 files changed, 86 insertions(+), 55 deletions(-) (limited to 'src/main/scala') 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 2daa634..21b4cd2 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala @@ -1,5 +1,5 @@ /* - * Copyright 2020, 2021 KRR Oxford + * Copyright 2020-2022 KRR Oxford * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,42 +16,31 @@ package uk.ac.ox.cs.rsacomb -import java.io.{File, PrintWriter} -import java.nio.file.{Path, Paths, InvalidPathException} -import java.util.HashMap -import scala.collection.JavaConverters._ -import tech.oxfordsemantic.jrdfox.client.UpdateType -import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term} -import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery - +import approximation.{Lowerbound,Upperbound} +import converter.Normalizer +import ontology.Ontology import util.{Logger, RDFoxUtil, RSA} -import sparql.ConjunctiveQuery - -import uk.ac.ox.cs.rsacomb.ontology.Ontology -import uk.ac.ox.cs.rsacomb.converter.Normalizer -import uk.ac.ox.cs.rsacomb.approximation.Approximation -/** Main entry point to the program */ object RSAComb extends App { - - /* Command-line options */ val config = RSAConfig.parse(args.toList) + RSAConfig describe config - /* Set logger level */ + /* Configure logger */ if (config.contains('logger)) Logger.level = config('logger).get[Logger.Level] - - /* Set answers output file */ if (config.contains('answers)) Logger.answers = config('answers).get[os.Path] /* Load original ontology and normalize it */ val ontopath = config('ontology).get[os.Path] - val data = config('data).get[List[os.Path]] - val ontology = Ontology(ontopath, data).normalize(new Normalizer) + val datapath = config('data).get[List[os.Path]] + val ontology = Ontology(ontopath, datapath).normalize(new Normalizer) - /* Approximate the ontology to RSA */ - val toRSA = config('approximation).get[Approximation[RSAOntology]] + /* Approximate the ontology if necessary */ + val toRSA = config('approximation).get[Symbol] match { + case 'lowerbound => new Lowerbound + case 'upperbound => new Upperbound + } val rsa = ontology approximate toRSA if (config contains 'queries) { @@ -61,11 +50,11 @@ object RSAComb extends App { RSA.Prefixes ) + /* Perform query answering */ val answers = rsa ask queries - /* Write answers to output file */ + /* Perform logging */ Logger write answers - /* Generate simulation script */ - Logger.generateSimulationScripts(data, queries) + Logger.generateSimulationScripts(datapath, queries) } } diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala index fe4b5f1..57c4f05 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala @@ -1,5 +1,5 @@ /* - * Copyright 2020, 2021 KRR Oxford + * Copyright 2020-2022 KRR Oxford * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,8 @@ package uk.ac.ox.cs.rsacomb import scala.collection.mutable.Map + import util.Logger -import approximation._ case class RSAOption[+T](opt: T) { def get[T]: T = opt.asInstanceOf[T] @@ -31,6 +31,7 @@ object RSAConfig { /** Help message */ private val help: String = """ + rsacomb - combined approach for CQ answering for RSA ontologies. USAGE @@ -59,25 +60,30 @@ object RSAConfig { directory is provided, all files in the directory (recursively) will be considered. + -x | --approximation + values available are "lowerupper" or "upperbound" corresponding + to the two algorithms for ontology approximation shipping by + default with RSAComb. You will need to change the source code to + expose custom approximation modules through the CLI. + + -t | --transitive + "upperbound" approximation specific option. Include property chain + axioms (and hence the more common transitive properties) when + computing the canonical model. + """ /** Default config values */ - private val default: Config = Map.empty + private val default: Config = Map( + 'transitive -> false, + 'data -> List.empty[os.Path], + 'approximation -> 'lowerbound + ) - /** Utility to exit the program with a custom message on stderr. - * - * The program will exit with error code 1 after printing the help - * message. + /** Parse a string into a path. * - * @param msg message printed to stderr. + * @throws an [[IllegalArgumentException]] on malformed path. */ - private def exit(msg: String): Nothing = { - System.err.println(msg) - System.err.println() - System.err.println(help) - sys.exit(1) - } - private def getPath(str: String): os.Path = try { os.Path(str, base = os.pwd) @@ -86,14 +92,27 @@ object RSAConfig { exit(s"'$str' is not a well formed path.") } - /** Parse arguments with default options + /** Utility to exit the program with a custom message on stderr. + * + * The program will exit with error after printing the help message. + * + * @param msg message printed to stderr. + * @param errno error code number (defaults to 1) + */ + private def exit(msg: String, errno: Int = 1): Nothing = { + System.err.println(msg) + System.err.println(help) + sys.exit(errno) + } + + /** Parse arguments with default options. * * @param args arguments list * @return map of config options */ def parse(args: List[String]): Config = parse(args, default) - /** Parse arguments + /** Parse arguments. * * @param args arguments list * @param config default configuration @@ -117,13 +136,11 @@ object RSAConfig { } case flag @ ("-a" | "--answers") :: answers :: tail => parse(tail, config += ('answers -> getPath(answers))) - case flag @ ("-x" | "--approximation") :: _approx :: tail => { - val approx = _approx match { - case "lowerbound" => new Lowerbound - case "upperbound" => new Upperbound - } - parse(tail, config += ('approximation -> approx)) + case flag @ ("-x" | "--approximation") :: approx :: tail => { + parse(tail, config += ('approximation -> Symbol(approx))) } + case flag @ ("-t" | "--transitive") :: tail => + parse(tail, config += ('transitive -> true)) case flag @ ("-q" | "--queries") :: _query :: tail => { val query = getPath(_query) val files = @@ -156,14 +173,39 @@ object RSAConfig { } } - /** Perform final checks on parsed options */ + /** Perform final checks on parsed options. + * + * @param config a parsed configuration + * @returns the input configuration, unchanged + */ private def finalise(config: Config): Config = { if (!config.contains('ontology)) exit("The following flag is mandatory: '-o' or '--ontology'.") - if (!config.contains('data)) - config += ('data -> List.empty[os.Path]) - if (!config.contains('approximation)) - config += ('approximation -> new Lowerbound) config } + + /** Generate summary of a config object suitable for printing + * + * @param config a parsed configuration + * @returns a string describing the configuration + */ + def describe(config: Config): Unit = { + config foreach { case (k,v) => k match { + case 'logger => Logger print s"Logger level: ${v.get[Logger.Level]}" + case 'ontology => Logger print s"Ontology file: ${v.get[os.Path]}" + case 'data => { + val paths = v.get[List[os.Path]] + val ellipsis = if (paths.length > 1) " [...]" else "" + Logger print s"Data files: ${paths.head}$ellipsis" + } + case 'queries => { + val paths = v.get[List[os.Path]] + val ellipsis = if (paths.length > 1) " [...]" else "" + Logger print s"Query files: ${paths.head}$ellipsis" + } + case 'answers => Logger print s"Path to answers: ${v.get[os.Path]}" + case 'approximation => Logger print s"Applied approximation: ${v.get[Symbol].name}" + case 'transitive => Logger print s"Include property chain axioms: ${v.get[Boolean]}" + }} + } } -- cgit v1.2.3