diff options
Diffstat (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala')
-rw-r--r-- | src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala new file mode 100644 index 0000000..4d96850 --- /dev/null +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAConfig.scala | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * Copyright 2020, 2021 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 | |||
17 | package uk.ac.ox.cs.rsacomb | ||
18 | |||
19 | import scala.collection.mutable.Map | ||
20 | import util.Logger | ||
21 | |||
22 | case class RSAOption[+T](opt: T) { | ||
23 | def get[T]: T = opt.asInstanceOf[T] | ||
24 | } | ||
25 | |||
26 | object RSAConfig { | ||
27 | type Config = Map[Symbol, RSAOption[Any]] | ||
28 | |||
29 | private implicit def toRSAOption[T](opt: T) = RSAOption[T](opt) | ||
30 | |||
31 | /** Help message */ | ||
32 | private val help: String = """ | ||
33 | rsacomb - combined approach for CQ answering for RSA ontologies. | ||
34 | |||
35 | USAGE | ||
36 | rsacomb [OPTIONS] <ontology> [<data> ...] | ||
37 | |||
38 | -h | -? | --help | ||
39 | print this help message | ||
40 | |||
41 | -l | --logger <level> | ||
42 | specify the logger verbosity. Values are: quiet, normal (default), | ||
43 | debug, verbose. | ||
44 | |||
45 | -a | --answers <file> | ||
46 | path to the output file for the answers to the query (in JSON | ||
47 | format) | ||
48 | |||
49 | -q | --queries <file> | ||
50 | path to a file containing a single SPARQL query. If no query | ||
51 | is provided, only the approximation to RSA will be performed. | ||
52 | |||
53 | -o | --ontology <file> | ||
54 | ontology file in OWL format. | ||
55 | |||
56 | -d | --data <file> | ||
57 | data files to be used alongside the ontology file. If a | ||
58 | directory is provided, all files in the directory (recursively) | ||
59 | will be considered. | ||
60 | |||
61 | """ | ||
62 | |||
63 | /** Default config values */ | ||
64 | private val default: Config = Map.empty | ||
65 | |||
66 | /** Utility to exit the program with a custom message on stderr. | ||
67 | * | ||
68 | * The program will exit with error code 1 after printing the help | ||
69 | * message. | ||
70 | * | ||
71 | * @param msg message printed to stderr. | ||
72 | */ | ||
73 | private def exit(msg: String): Nothing = { | ||
74 | System.err.println(msg) | ||
75 | System.err.println() | ||
76 | System.err.println(help) | ||
77 | sys.exit(1) | ||
78 | } | ||
79 | |||
80 | private def getPath(str: String): os.Path = | ||
81 | try { | ||
82 | os.Path(str, base = os.pwd) | ||
83 | } catch { | ||
84 | case e: IllegalArgumentException => | ||
85 | exit(s"'$str' is not a well formed path.") | ||
86 | } | ||
87 | |||
88 | /** Parse arguments with default options | ||
89 | * | ||
90 | * @param args arguments list | ||
91 | * @return map of config options | ||
92 | */ | ||
93 | def parse(args: List[String]): Config = parse(args, default) | ||
94 | |||
95 | /** Parse arguments | ||
96 | * | ||
97 | * @param args arguments list | ||
98 | * @param config default configuration | ||
99 | * @return map of config options | ||
100 | */ | ||
101 | def parse(args: List[String], config: Config): Config = { | ||
102 | args match { | ||
103 | case Nil => finalise(config) | ||
104 | case flag @ ("-h" | "-?" | "--help") :: _ => { | ||
105 | println(help) | ||
106 | sys.exit(0) | ||
107 | } | ||
108 | case flag @ ("-l" | "--logger") :: _level :: tail => { | ||
109 | val level = _level match { | ||
110 | case "quiet" => Logger.QUIET | ||
111 | case "debug" => Logger.DEBUG | ||
112 | case "verbose" => Logger.VERBOSE | ||
113 | case _ => Logger.NORMAL | ||
114 | } | ||
115 | parse(tail, config += ('logger -> level)) | ||
116 | } | ||
117 | case flag @ ("-a" | "--answers") :: answers :: tail => | ||
118 | parse(tail, config += ('answers -> getPath(answers))) | ||
119 | case flag @ ("-q" | "--queries") :: _query :: tail => { | ||
120 | val query = getPath(_query) | ||
121 | if (!os.isFile(query)) | ||
122 | exit(s"'${_query}' is not a valid filename.") | ||
123 | parse(tail, config += ('queries -> query)) | ||
124 | } | ||
125 | case flag @ ("-o" | "--ontology") :: _ontology :: tail => { | ||
126 | val ontology = getPath(_ontology) | ||
127 | if (!os.isFile(ontology)) | ||
128 | exit(s"'${_ontology}' is not a valid filename.") | ||
129 | parse(tail, config += ('ontology -> ontology)) | ||
130 | } | ||
131 | case flag @ ("-d" | "--data") :: _data :: tail => { | ||
132 | val data = getPath(_data) | ||
133 | val files = | ||
134 | if (os.isFile(data)) | ||
135 | Seq(data) | ||
136 | else if (os.isDir(data)) | ||
137 | os.walk(data).filter(os.isFile) | ||
138 | else | ||
139 | exit(s"'${_data}' is not a valid path.") | ||
140 | parse(tail, config += ('data -> files)) | ||
141 | } | ||
142 | case a => exit(s"Invalid sequence of arguments '${a.mkString(" ")}'.") | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /** Perform final checks on parsed options */ | ||
147 | private def finalise(config: Config): Config = { | ||
148 | if (!config.contains('ontology)) | ||
149 | exit("The following flag is mandatory: '-o' or '--ontology'.") | ||
150 | if (!config.contains('data)) | ||
151 | config += ('data -> List.empty[os.Path]) | ||
152 | config | ||
153 | } | ||
154 | } | ||