aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/uk/ac/ox/cs/acqua/util
diff options
context:
space:
mode:
authorFederico Igne <federico.igne@cs.ox.ac.uk>2022-05-11 12:35:56 +0100
committerFederico Igne <federico.igne@cs.ox.ac.uk>2022-05-11 12:35:56 +0100
commit32fe8f94255b913c570275043a3c056eaa4ec07b (patch)
tree2a370c3998db1eab758f214f16f2cebc3fd2ef34 /src/main/scala/uk/ac/ox/cs/acqua/util
parenteaa8ed73aec7ca0ba02eb3e1c954388b8dbfc2cd (diff)
downloadACQuA-32fe8f94255b913c570275043a3c056eaa4ec07b.tar.gz
ACQuA-32fe8f94255b913c570275043a3c056eaa4ec07b.zip
Implement stub for query answering procedure
Diffstat (limited to 'src/main/scala/uk/ac/ox/cs/acqua/util')
-rw-r--r--src/main/scala/uk/ac/ox/cs/acqua/util/AcquaConfig.scala211
1 files changed, 211 insertions, 0 deletions
diff --git a/src/main/scala/uk/ac/ox/cs/acqua/util/AcquaConfig.scala b/src/main/scala/uk/ac/ox/cs/acqua/util/AcquaConfig.scala
new file mode 100644
index 0000000..675a592
--- /dev/null
+++ b/src/main/scala/uk/ac/ox/cs/acqua/util/AcquaConfig.scala
@@ -0,0 +1,211 @@
1/*
2 * Copyright 2021,2022 KRR Oxford
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package uk.ac.ox.cs.acqua.util
18
19import scala.collection.mutable.Map
20
21//import util.Logger
22
23case class AcquaOption[+T](opt: T) {
24 def get[T]: T = opt.asInstanceOf[T]
25}
26
27object AcquaConfig {
28 type Config = Map[Symbol, AcquaOption[Any]]
29
30 private implicit def toRSAOption[T](opt: T) = AcquaOption[T](opt)
31
32 /** Help message */
33 private val help: String = """
34
35 rsacomb - combined approach for CQ answering for RSA ontologies.
36
37 USAGE
38 rsacomb [OPTIONS] <ontology> [<data> ...]
39
40 -h | -? | --help
41 print this help message
42
43 -l | --logger <level>
44 specify the logger verbosity. Values are: quiet, normal (default),
45 debug, verbose.
46
47 -a | --answers <file>
48 path to the output file for the answers to the query (in JSON
49 format)
50
51 -q | --queries <file>
52 path to a file containing a single SPARQL query. If no query
53 is provided, only the approximation to RSA will be performed.
54
55 -o | --ontology <file>
56 ontology file in OWL format.
57
58 -d | --data <file>
59 data files to be used alongside the ontology file. If a
60 directory is provided, all files in the directory (recursively)
61 will be considered.
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
74 """
75
76 /** Default config values */
77 private val default: Config = Map(
78 'transitive -> false,
79 'data -> List.empty[os.Path],
80 'approximation -> 'lowerbound
81 )
82
83 /** Parse a string into a path.
84 *
85 * @throws an [[IllegalArgumentException]] on malformed path.
86 */
87 private def getPath(str: String): os.Path =
88 try {
89 os.Path(str, base = os.pwd)
90 } catch {
91 case e: IllegalArgumentException =>
92 exit(s"'$str' is not a well formed path.")
93 }
94
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.
109 *
110 * @param args arguments list
111 * @return map of config options
112 */
113 def parse(args: List[String]): Config = parse(args, default)
114
115 /** Parse arguments.
116 *
117 * @param args arguments list
118 * @param config default configuration
119 * @return map of config options
120 */
121 def parse(args: List[String], config: Config): Config = {
122 args match {
123 case Nil => finalise(config)
124 case flag @ ("-h" | "-?" | "--help") :: _ => {
125 println(help)
126 sys.exit(0)
127 }
128 case flag @ ("-l" | "--logger") :: _level :: tail => {
129 // val level = _level match {
130 // case "quiet" => Logger.QUIET
131 // case "debug" => Logger.DEBUG
132 // case "verbose" => Logger.VERBOSE
133 // case _ => Logger.NORMAL
134 // }
135 parse(tail, config += ('logger -> _level))
136 }
137 case flag @ ("-a" | "--answers") :: answers :: tail =>
138 parse(tail, config += ('answers -> getPath(answers)))
139 case flag @ ("-x" | "--approximation") :: approx :: tail => {
140 parse(tail, config += ('approximation -> Symbol(approx)))
141 }
142 case flag @ ("-t" | "--transitive") :: tail =>
143 parse(tail, config += ('transitive -> true))
144 case flag @ ("-q" | "--queries") :: _query :: tail => {
145 val query = getPath(_query)
146 val files =
147 if (os.isFile(query))
148 List(query)
149 else if (os.isDir(query))
150 os.walk(query).filter(os.isFile).toList
151 else
152 exit(s"'${_query}' is not a valid path.")
153 parse(tail, config += ('queries -> files))
154 }
155 case flag @ ("-o" | "--ontology") :: _ontology :: tail => {
156 val ontology = getPath(_ontology)
157 if (!os.isFile(ontology))
158 exit(s"'${_ontology}' is not a valid filename.")
159 parse(tail, config += ('ontology -> ontology))
160 }
161 case flag @ ("-d" | "--data") :: _data :: tail => {
162 val data = getPath(_data)
163 val files =
164 if (os.isFile(data))
165 List(data)
166 else if (os.isDir(data)) {
167 os.walk(data).filter(os.isFile).toList
168 }else
169 exit(s"'${_data}' is not a valid path.")
170 parse(tail, config += ('data -> files))
171 }
172 case a => exit(s"Invalid sequence of arguments '${a.mkString(" ")}'.")
173 }
174 }
175
176 /** Perform final checks on parsed options.
177 *
178 * @param config a parsed configuration
179 * @returns the input configuration, unchanged
180 */
181 private def finalise(config: Config): Config = {
182 if (!config.contains('ontology))
183 exit("The following flag is mandatory: '-o' or '--ontology'.")
184 config
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 }
211}