aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/uk/ac/ox/cs
diff options
context:
space:
mode:
authorFederico Igne <federico.igne@cs.ox.ac.uk>2021-01-30 10:46:23 +0000
committerFederico Igne <federico.igne@cs.ox.ac.uk>2021-01-30 10:48:29 +0000
commitd04e2839689c4291afb4beb9a1913bb38fac1cd1 (patch)
tree365e5ea2ef138e83ff46ecce72c716de6686e78e /src/main/scala/uk/ac/ox/cs
parent87b180f1de0e1c30a4624e546825b77c2edf9bbe (diff)
downloadRSAComb-d04e2839689c4291afb4beb9a1913bb38fac1cd1.tar.gz
RSAComb-d04e2839689c4291afb4beb9a1913bb38fac1cd1.zip
Introduce a better system to handle command line input
Diffstat (limited to 'src/main/scala/uk/ac/ox/cs')
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala200
1 files changed, 142 insertions, 58 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 bf96a31..909cfdd 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala
@@ -10,6 +10,106 @@ import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery
10import util.{Logger, RDFoxUtil, RSA} 10import util.{Logger, RDFoxUtil, RSA}
11import sparql.ConjunctiveQuery 11import sparql.ConjunctiveQuery
12 12
13case class RSAOption[+T](opt: T) {
14 def get[T]: T = opt.asInstanceOf[T]
15}
16
17object RSAConfig {
18 type Config = Map[Symbol, RSAOption[Any]]
19
20 private implicit def toRSAOption[T](opt: T) = RSAOption[T](opt)
21
22 /** Help message */
23 private val help: String = """
24 rsacomb - combined approach for CQ answering for RSA ontologies.
25
26 USAGE
27 rsacomb [OPTIONS] <ontology> [<data> ...]
28
29 -h | -? | --help
30 print this help message
31
32 --rsacheck-only
33 only perform the RSA check without performing any query answering.
34
35 -q <file> | --query <file>
36 path to a file containing a single SPARQL query
37
38 <ontology>
39 file containing the ontology
40
41 <data>
42 one or more data files
43
44 """
45
46 /** Default config values */
47 private val default = Map(
48 'rsacheckonly -> RSAOption[Boolean](false)
49 )
50
51 /** Utility to exit the program with a custom message on stderr.
52 *
53 * The program will exit with error code 1 after printing the help
54 * message.
55 *
56 * @param msg message printed to stderr.
57 */
58 private def exit(msg: String): Nothing = {
59 System.err.println(msg)
60 System.err.println()
61 System.err.println(help)
62 sys.exit(1)
63 }
64
65 /** Parse arguments with default options
66 *
67 * @param args arguments list
68 */
69 def parse(args: List[String]): Config = parse(args, default)
70
71 /** Parse arguments
72 *
73 * @param args arguments list
74 * @param config default configuration
75 */
76 def parse(args: List[String], config: Config): Config = {
77 args match {
78 case flag @ ("-h" | "-?" | "--help") :: _ => {
79 println(help)
80 sys.exit(0)
81 }
82 case "--rsacheck-only" :: tail =>
83 parse(tail, config ++ Map('rsacheckonly -> true))
84 case flag @ ("-q" | "--query") :: _query :: tail => {
85 val query = new File(_query)
86 if (!query.isFile)
87 exit(s"'$query' is not a valid filename.")
88 parse(tail, config ++ Map('query -> query))
89 }
90 case _ontology :: _data => {
91 val ontology = new File(_ontology)
92 val data = _data.map(new File(_))
93 (ontology :: data) foreach { (file) =>
94 if (!file.isFile)
95 exit(s"'$file' is not a valid filename.")
96 }
97 finalise(config ++ Map('ontology -> ontology, 'data -> data))
98 }
99 case a => exit(s"Invalid sequence of arguments '${a.mkString(" ")}'.")
100 }
101 }
102
103 /** Perform final checks on parsed options */
104 private def finalise(config: Config): Config = {
105 // Query file is mandatory unless only the RSA check is required.
106 if (!config('rsacheckonly).get[Boolean] && !config.contains('query))
107 exit(s"Query file was not provided.")
108
109 config
110 }
111}
112
13/** Entry point of the program. 113/** Entry point of the program.
14 * 114 *
15 * The executable expects a SPARQL query and a non-empty sequence of 115 * The executable expects a SPARQL query and a non-empty sequence of
@@ -24,72 +124,56 @@ import sparql.ConjunctiveQuery
24 */ 124 */
25object RSAComb extends App { 125object RSAComb extends App {
26 126
27 val help: String = """ 127 val config = RSAConfig.parse(args.toList)
28 rsacomb - combined approach for CQ answering for RSA ontologies.
29
30 USAGE
31 rsacomb <query> <ontology> [...]
32
33 where
34 - query: path to a file containing a single SPARQL query
35 - ontology: one or more ontology files
36
37 """
38
39 if (args.length < 2) {
40 println(help)
41 sys.exit;
42 }
43
44 val queryPath = new File(args(0))
45 val ontoPaths = args.drop(1).map(new File(_))
46
47 if (!queryPath.isFile || !ontoPaths.forall(_.isFile)) {
48 println("The provided arguments are not regular files.\n\n")
49 println(help)
50 sys.exit;
51 }
52 128
53 val ontology = RSAOntology(ontoPaths: _*) 129 val ontology =
130 RSAOntology(config('ontology).get[File], config('data).get[List[File]]: _*)
54 if (ontology.isRSA) { 131 if (ontology.isRSA) {
55 132
56 Logger print "Ontology is RSA!" 133 Logger print "Ontology is RSA!"
57 134
58 val query = RDFoxUtil.loadQueryFromFile(queryPath.getAbsoluteFile) 135 if (!config('rsacheckonly).get[Boolean]) {
59 136 val query =
60 ConjunctiveQuery.parse(query) match { 137 RDFoxUtil.loadQueryFromFile(config('query).get[File].getAbsoluteFile)
61 case Some(query) => { 138
62 val answers = ontology ask query 139 ConjunctiveQuery.parse(query) match {
63 Logger.print(s"$answers", Logger.QUIET) 140 case Some(query) => {
64 Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})" 141 val answers = ontology ask query
65 142 Logger.print(s"$answers", Logger.QUIET)
66 /* Additional DEBUG information */ 143 Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})"
67 if (Logger.level >= Logger.DEBUG) { 144
68 /* Unfiltered rules */ 145 // /* Additional DEBUG information */
69 val unfiltered = ontology askUnfiltered query 146 // if (Logger.level >= Logger.DEBUG) {
70 unfiltered map { u => 147 // /* Unfiltered rules */
71 Logger print s"Number of unfiltered answers: ${u.length} (${u.map(_._1).sum})." 148 // val unfiltered = ontology askUnfiltered query
72 149 // unfiltered map { u =>
73 /* Spurious answers */ 150 // Logger print s"Number of unfiltered answers: ${u.length} (${u.map(_._1).sum})."
74 val spurious = { 151
75 val variables = query.variables.length 152 // /* Spurious answers */
76 val sp = RDFoxUtil.buildDescriptionQuery("SP", variables) 153 // val spurious = {
77 ontology.queryDataStore(query, sp, RSA.Prefixes) 154 // val variables = query.variables.length
78 } 155 // val sp = RDFoxUtil.buildDescriptionQuery("SP", variables)
79 spurious map { s => 156 // ontology.queryDataStore(query, sp, RSA.Prefixes)
80 Logger print s"Number of spurious answers: ${s.length} (${s.map(_._1).sum})" 157 // }
81 158 // spurious map { s =>
82 /* Spurious/unfiltered percentage */ 159 // Logger print s"Number of spurious answers: ${s.length} (${s.map(_._1).sum})"
83 val perc = 160
84 if (u.length > 0) (s.length / u.length.toFloat) * 100 else 0 161 // /* Spurious/unfiltered percentage */
85 Logger print s"Percentage of spurious answers: $perc%" 162 // val perc =
86 } 163 // if (u.length > 0) (s.length / u.length.toFloat) * 100 else 0
87 } 164 // Logger print s"Percentage of spurious answers: $perc%"
165 // }
166 // }
167 // }
88 } 168 }
169 case None =>
170 throw new RuntimeException("Submitted query is not conjunctive")
89 } 171 }
90 case None =>
91 throw new RuntimeException("Submitted query is not conjunctive")
92 } 172 }
93 173
174 } else {
175
176 Logger print "Ontology is not RSA!"
177
94 } 178 }
95} 179}