aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala')
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala134
1 files changed, 10 insertions, 124 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 24bda1f..121c65f 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala
@@ -19,7 +19,6 @@ package uk.ac.ox.cs.rsacomb
19import java.io.{File, PrintWriter} 19import java.io.{File, PrintWriter}
20import java.nio.file.{Path, Paths, InvalidPathException} 20import java.nio.file.{Path, Paths, InvalidPathException}
21import java.util.HashMap 21import java.util.HashMap
22import scala.collection.mutable.Map
23import scala.collection.JavaConverters._ 22import scala.collection.JavaConverters._
24import tech.oxfordsemantic.jrdfox.client.UpdateType 23import tech.oxfordsemantic.jrdfox.client.UpdateType
25import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term} 24import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term}
@@ -32,129 +31,15 @@ import uk.ac.ox.cs.rsacomb.ontology.Ontology
32import uk.ac.ox.cs.rsacomb.converter.Normalizer 31import uk.ac.ox.cs.rsacomb.converter.Normalizer
33import uk.ac.ox.cs.rsacomb.approximation.{Upperbound, Lowerbound} 32import uk.ac.ox.cs.rsacomb.approximation.{Upperbound, Lowerbound}
34 33
35case class RSAOption[+T](opt: T) {
36 def get[T]: T = opt.asInstanceOf[T]
37}
38
39object RSAConfig {
40 type Config = Map[Symbol, RSAOption[Any]]
41
42 private implicit def toRSAOption[T](opt: T) = RSAOption[T](opt)
43
44 /** Help message */
45 private val help: String = """
46 rsacomb - combined approach for CQ answering for RSA ontologies.
47
48 USAGE
49 rsacomb [OPTIONS] <ontology> [<data> ...]
50
51 -h | -? | --help
52 print this help message
53
54 -l | --logger <level>
55 specify the logger verbosity. Values are: quiet, normal (default),
56 debug, verbose.
57
58 -o | --output <file>
59 path to the output file for the answers to the query (in JSON
60 format)
61
62 -q | --queries <file>
63 path to a file containing a single SPARQL query. If no query
64 is provided, only the approximation to RSA will be performed.
65
66 <ontology>
67 file containing the ontology
68
69 <data>
70 one or more data files
71
72 """
73
74 /** Default config values */
75 private val default: Config = Map.empty
76
77 /** Utility to exit the program with a custom message on stderr.
78 *
79 * The program will exit with error code 1 after printing the help
80 * message.
81 *
82 * @param msg message printed to stderr.
83 */
84 private def exit(msg: String): Nothing = {
85 System.err.println(msg)
86 System.err.println()
87 System.err.println(help)
88 sys.exit(1)
89 }
90
91 private def getPath(str: String): os.Path =
92 try {
93 os.Path(str, base = os.pwd)
94 } catch {
95 case e: IllegalArgumentException =>
96 exit(s"'$str' is not a well formed path.")
97 }
98
99 /** Parse arguments with default options
100 *
101 * @param args arguments list
102 * @return map of config options
103 */
104 def parse(args: List[String]): Config = parse(args, default)
105
106 /** Parse arguments
107 *
108 * @param args arguments list
109 * @param config default configuration
110 * @return map of config options
111 */
112 def parse(args: List[String], config: Config): Config = {
113 args match {
114 case flag @ ("-h" | "-?" | "--help") :: _ => {
115 println(help)
116 sys.exit(0)
117 }
118 case flag @ ("-l" | "--logger") :: _level :: tail => {
119 val level = _level match {
120 case "quiet" => Logger.QUIET
121 case "debug" => Logger.DEBUG
122 case "verbose" => Logger.VERBOSE
123 case _ => Logger.NORMAL
124 }
125 parse(tail, config += ('logger -> level))
126 }
127 case flag @ ("-o" | "--output") :: output :: tail =>
128 parse(tail, config += ('output -> getPath(output)))
129 case flag @ ("-q" | "--queries") :: _query :: tail => {
130 val query = getPath(_query)
131 if (!os.isFile(query))
132 exit(s"'${_query}' is not a valid filename.")
133 parse(tail, config += ('queries -> query))
134 }
135 case _ontology :: _data => {
136 val ontology = getPath(_ontology)
137 val data = _data map getPath
138 (ontology :: data) foreach { (path) =>
139 if (!os.isFile(path))
140 exit(s"'$path' is not a valid filename.")
141 }
142 finalise(config += ('ontology -> ontology) += ('data -> data))
143 }
144 case a => exit(s"Invalid sequence of arguments '${a.mkString(" ")}'.")
145 }
146 }
147
148 /** Perform final checks on parsed options */
149 private def finalise(config: Config): Config = config
150}
151
152/** Main entry point to the program */ 34/** Main entry point to the program */
153object RSAComb extends App { 35object RSAComb extends App {
154 36
155 /* Command-line options */ 37 /* Command-line options */
156 val config = RSAConfig.parse(args.toList) 38 val config = RSAConfig.parse(args.toList)
157 Logger.level = config('logger).get[Logger.Level] 39
40 /* Set logger level */
41 if (config.contains('logger))
42 Logger.level = config('logger).get[Logger.Level]
158 43
159 /* Load original ontology and normalize it */ 44 /* Load original ontology and normalize it */
160 val ontology = Ontology( 45 val ontology = Ontology(
@@ -177,11 +62,12 @@ object RSAComb extends App {
177 val answers = rsa ask queries 62 val answers = rsa ask queries
178 63
179 /* Write answers to output file */ 64 /* Write answers to output file */
180 os.write( 65 if (config.contains('answers))
181 config('output).get[os.Path], 66 os.write(
182 ujson.write(ujson.Arr(answers.map(_.toJSON)), indent = 4), 67 config('answers).get[os.Path],
183 createFolders = true 68 ujson.write(ujson.Arr(answers.map(_.toJSON)), indent = 4),
184 ) 69 createFolders = true
70 )
185 71
186 // Logger.print(s"$answers", Logger.VERBOSE) 72 // Logger.print(s"$answers", Logger.VERBOSE)
187 // Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})" 73 // Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})"