aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Igne <federico.igne@cs.ox.ac.uk>2022-05-09 12:30:20 +0100
committerFederico Igne <federico.igne@cs.ox.ac.uk>2022-05-09 12:30:20 +0100
commit98312cd3c355a2b036edf5236dfcba755da9a17a (patch)
tree02ee6d77e0eec89610d4ad310557bc1bb6c2394f
parent155f04db8138d62b3abc2eb777b8453560bbb594 (diff)
downloadRSAComb-98312cd3c355a2b036edf5236dfcba755da9a17a.tar.gz
RSAComb-98312cd3c355a2b036edf5236dfcba755da9a17a.zip
Refactor code
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala43
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala98
2 files changed, 86 insertions, 55 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 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 @@
1/* 1/*
2 * Copyright 2020, 2021 KRR Oxford 2 * Copyright 2020-2022 KRR Oxford
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -16,42 +16,31 @@
16 16
17package uk.ac.ox.cs.rsacomb 17package uk.ac.ox.cs.rsacomb
18 18
19import java.io.{File, PrintWriter} 19import approximation.{Lowerbound,Upperbound}
20import java.nio.file.{Path, Paths, InvalidPathException} 20import converter.Normalizer
21import java.util.HashMap 21import ontology.Ontology
22import scala.collection.JavaConverters._
23import tech.oxfordsemantic.jrdfox.client.UpdateType
24import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term}
25import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery
26
27import util.{Logger, RDFoxUtil, RSA} 22import util.{Logger, RDFoxUtil, RSA}
28import sparql.ConjunctiveQuery
29
30import uk.ac.ox.cs.rsacomb.ontology.Ontology
31import uk.ac.ox.cs.rsacomb.converter.Normalizer
32import uk.ac.ox.cs.rsacomb.approximation.Approximation
33 23
34/** Main entry point to the program */
35object RSAComb extends App { 24object RSAComb extends App {
36
37 /* Command-line options */
38 val config = RSAConfig.parse(args.toList) 25 val config = RSAConfig.parse(args.toList)
26 RSAConfig describe config
39 27
40 /* Set logger level */ 28 /* Configure logger */
41 if (config.contains('logger)) 29 if (config.contains('logger))
42 Logger.level = config('logger).get[Logger.Level] 30 Logger.level = config('logger).get[Logger.Level]
43
44 /* Set answers output file */
45 if (config.contains('answers)) 31 if (config.contains('answers))
46 Logger.answers = config('answers).get[os.Path] 32 Logger.answers = config('answers).get[os.Path]
47 33
48 /* Load original ontology and normalize it */ 34 /* Load original ontology and normalize it */
49 val ontopath = config('ontology).get[os.Path] 35 val ontopath = config('ontology).get[os.Path]
50 val data = config('data).get[List[os.Path]] 36 val datapath = config('data).get[List[os.Path]]
51 val ontology = Ontology(ontopath, data).normalize(new Normalizer) 37 val ontology = Ontology(ontopath, datapath).normalize(new Normalizer)
52 38
53 /* Approximate the ontology to RSA */ 39 /* Approximate the ontology if necessary */
54 val toRSA = config('approximation).get[Approximation[RSAOntology]] 40 val toRSA = config('approximation).get[Symbol] match {
41 case 'lowerbound => new Lowerbound
42 case 'upperbound => new Upperbound
43 }
55 val rsa = ontology approximate toRSA 44 val rsa = ontology approximate toRSA
56 45
57 if (config contains 'queries) { 46 if (config contains 'queries) {
@@ -61,11 +50,11 @@ object RSAComb extends App {
61 RSA.Prefixes 50 RSA.Prefixes
62 ) 51 )
63 52
53 /* Perform query answering */
64 val answers = rsa ask queries 54 val answers = rsa ask queries
65 55
66 /* Write answers to output file */ 56 /* Perform logging */
67 Logger write answers 57 Logger write answers
68 /* Generate simulation script */ 58 Logger.generateSimulationScripts(datapath, queries)
69 Logger.generateSimulationScripts(data, queries)
70 } 59 }
71} 60}
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 @@
1/* 1/*
2 * Copyright 2020, 2021 KRR Oxford 2 * Copyright 2020-2022 KRR Oxford
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
@@ -17,8 +17,8 @@
17package uk.ac.ox.cs.rsacomb 17package uk.ac.ox.cs.rsacomb
18 18
19import scala.collection.mutable.Map 19import scala.collection.mutable.Map
20
20import util.Logger 21import util.Logger
21import approximation._
22 22
23case class RSAOption[+T](opt: T) { 23case class RSAOption[+T](opt: T) {
24 def get[T]: T = opt.asInstanceOf[T] 24 def get[T]: T = opt.asInstanceOf[T]
@@ -31,6 +31,7 @@ object RSAConfig {
31 31
32 /** Help message */ 32 /** Help message */
33 private val help: String = """ 33 private val help: String = """
34
34 rsacomb - combined approach for CQ answering for RSA ontologies. 35 rsacomb - combined approach for CQ answering for RSA ontologies.
35 36
36 USAGE 37 USAGE
@@ -59,25 +60,30 @@ object RSAConfig {
59 directory is provided, all files in the directory (recursively) 60 directory is provided, all files in the directory (recursively)
60 will be considered. 61 will be considered.
61 62
63 -x | --approximation <string>
64 values available are "lowerupper" or "upperbound" corresponding
65 to the two algorithms for ontology approximation shipping by
66 default with RSAComb. You will need to change the source code to
67 expose custom approximation modules through the CLI.
68
69 -t | --transitive
70 "upperbound" approximation specific option. Include property chain
71 axioms (and hence the more common transitive properties) when
72 computing the canonical model.
73
62 """ 74 """
63 75
64 /** Default config values */ 76 /** Default config values */
65 private val default: Config = Map.empty 77 private val default: Config = Map(
78 'transitive -> false,
79 'data -> List.empty[os.Path],
80 'approximation -> 'lowerbound
81 )
66 82
67 /** Utility to exit the program with a custom message on stderr. 83 /** Parse a string into a path.
68 *
69 * The program will exit with error code 1 after printing the help
70 * message.
71 * 84 *
72 * @param msg message printed to stderr. 85 * @throws an [[IllegalArgumentException]] on malformed path.
73 */ 86 */
74 private def exit(msg: String): Nothing = {
75 System.err.println(msg)
76 System.err.println()
77 System.err.println(help)
78 sys.exit(1)
79 }
80
81 private def getPath(str: String): os.Path = 87 private def getPath(str: String): os.Path =
82 try { 88 try {
83 os.Path(str, base = os.pwd) 89 os.Path(str, base = os.pwd)
@@ -86,14 +92,27 @@ object RSAConfig {
86 exit(s"'$str' is not a well formed path.") 92 exit(s"'$str' is not a well formed path.")
87 } 93 }
88 94
89 /** Parse arguments with default options 95 /** Utility to exit the program with a custom message on stderr.
96 *
97 * The program will exit with error after printing the help message.
98 *
99 * @param msg message printed to stderr.
100 * @param errno error code number (defaults to 1)
101 */
102 private def exit(msg: String, errno: Int = 1): Nothing = {
103 System.err.println(msg)
104 System.err.println(help)
105 sys.exit(errno)
106 }
107
108 /** Parse arguments with default options.
90 * 109 *
91 * @param args arguments list 110 * @param args arguments list
92 * @return map of config options 111 * @return map of config options
93 */ 112 */
94 def parse(args: List[String]): Config = parse(args, default) 113 def parse(args: List[String]): Config = parse(args, default)
95 114
96 /** Parse arguments 115 /** Parse arguments.
97 * 116 *
98 * @param args arguments list 117 * @param args arguments list
99 * @param config default configuration 118 * @param config default configuration
@@ -117,13 +136,11 @@ object RSAConfig {
117 } 136 }
118 case flag @ ("-a" | "--answers") :: answers :: tail => 137 case flag @ ("-a" | "--answers") :: answers :: tail =>
119 parse(tail, config += ('answers -> getPath(answers))) 138 parse(tail, config += ('answers -> getPath(answers)))
120 case flag @ ("-x" | "--approximation") :: _approx :: tail => { 139 case flag @ ("-x" | "--approximation") :: approx :: tail => {
121 val approx = _approx match { 140 parse(tail, config += ('approximation -> Symbol(approx)))
122 case "lowerbound" => new Lowerbound
123 case "upperbound" => new Upperbound
124 }
125 parse(tail, config += ('approximation -> approx))
126 } 141 }
142 case flag @ ("-t" | "--transitive") :: tail =>
143 parse(tail, config += ('transitive -> true))
127 case flag @ ("-q" | "--queries") :: _query :: tail => { 144 case flag @ ("-q" | "--queries") :: _query :: tail => {
128 val query = getPath(_query) 145 val query = getPath(_query)
129 val files = 146 val files =
@@ -156,14 +173,39 @@ object RSAConfig {
156 } 173 }
157 } 174 }
158 175
159 /** Perform final checks on parsed options */ 176 /** Perform final checks on parsed options.
177 *
178 * @param config a parsed configuration
179 * @returns the input configuration, unchanged
180 */
160 private def finalise(config: Config): Config = { 181 private def finalise(config: Config): Config = {
161 if (!config.contains('ontology)) 182 if (!config.contains('ontology))
162 exit("The following flag is mandatory: '-o' or '--ontology'.") 183 exit("The following flag is mandatory: '-o' or '--ontology'.")
163 if (!config.contains('data))
164 config += ('data -> List.empty[os.Path])
165 if (!config.contains('approximation))
166 config += ('approximation -> new Lowerbound)
167 config 184 config
168 } 185 }
186
187 /** Generate summary of a config object suitable for printing
188 *
189 * @param config a parsed configuration
190 * @returns a string describing the configuration
191 */
192 def describe(config: Config): Unit = {
193 config foreach { case (k,v) => k match {
194 case 'logger => Logger print s"Logger level: ${v.get[Logger.Level]}"
195 case 'ontology => Logger print s"Ontology file: ${v.get[os.Path]}"
196 case 'data => {
197 val paths = v.get[List[os.Path]]
198 val ellipsis = if (paths.length > 1) " [...]" else ""
199 Logger print s"Data files: ${paths.head}$ellipsis"
200 }
201 case 'queries => {
202 val paths = v.get[List[os.Path]]
203 val ellipsis = if (paths.length > 1) " [...]" else ""
204 Logger print s"Query files: ${paths.head}$ellipsis"
205 }
206 case 'answers => Logger print s"Path to answers: ${v.get[os.Path]}"
207 case 'approximation => Logger print s"Applied approximation: ${v.get[Symbol].name}"
208 case 'transitive => Logger print s"Include property chain axioms: ${v.get[Boolean]}"
209 }}
210 }
169} 211}