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.scala165
1 files changed, 43 insertions, 122 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 258c226..121c65f 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala
@@ -16,7 +16,8 @@
16 16
17package uk.ac.ox.cs.rsacomb 17package uk.ac.ox.cs.rsacomb
18 18
19import java.io.File 19import java.io.{File, PrintWriter}
20import java.nio.file.{Path, Paths, InvalidPathException}
20import java.util.HashMap 21import java.util.HashMap
21import scala.collection.JavaConverters._ 22import scala.collection.JavaConverters._
22import tech.oxfordsemantic.jrdfox.client.UpdateType 23import tech.oxfordsemantic.jrdfox.client.UpdateType
@@ -28,97 +29,7 @@ import sparql.ConjunctiveQuery
28 29
29import uk.ac.ox.cs.rsacomb.ontology.Ontology 30import uk.ac.ox.cs.rsacomb.ontology.Ontology
30import uk.ac.ox.cs.rsacomb.converter.Normalizer 31import uk.ac.ox.cs.rsacomb.converter.Normalizer
31import uk.ac.ox.cs.rsacomb.approximation.LowerBound 32import uk.ac.ox.cs.rsacomb.approximation.{Upperbound, Lowerbound}
32
33case class RSAOption[+T](opt: T) {
34 def get[T]: T = opt.asInstanceOf[T]
35}
36
37object RSAConfig {
38 type Config = Map[Symbol, RSAOption[Any]]
39
40 private implicit def toRSAOption[T](opt: T) = RSAOption[T](opt)
41
42 /** Help message */
43 private val help: String = """
44 rsacomb - combined approach for CQ answering for RSA ontologies.
45
46 USAGE
47 rsacomb [OPTIONS] <ontology> [<data> ...]
48
49 -h | -? | --help
50 print this help message
51
52 -q <file> | --query <file>
53 path to a file containing a single SPARQL query. If no query
54 is provided, only the approximation to RSA will be performed.
55
56 <ontology>
57 file containing the ontology
58
59 <data>
60 one or more data files
61
62 """
63
64 /** Default config values */
65 private val default: Config = Map.empty
66
67 /** Utility to exit the program with a custom message on stderr.
68 *
69 * The program will exit with error code 1 after printing the help
70 * message.
71 *
72 * @param msg message printed to stderr.
73 */
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 /** Parse arguments with default options
82 *
83 * @param args arguments list
84 * @return map of config options
85 */
86 def parse(args: List[String]): Config = parse(args, default)
87
88 /** Parse arguments
89 *
90 * @param args arguments list
91 * @param config default configuration
92 * @return map of config options
93 */
94 def parse(args: List[String], config: Config): Config = {
95 args match {
96 case flag @ ("-h" | "-?" | "--help") :: _ => {
97 println(help)
98 sys.exit(0)
99 }
100 case flag @ ("-q" | "--query") :: _query :: tail => {
101 val query = new File(_query)
102 if (!query.isFile)
103 exit(s"'$query' is not a valid filename.")
104 parse(tail, config ++ Map('query -> query))
105 }
106 case _ontology :: _data => {
107 val ontology = new File(_ontology)
108 val data = _data.map(new File(_))
109 (ontology :: data) foreach { (file) =>
110 if (!file.isFile)
111 exit(s"'$file' is not a valid filename.")
112 }
113 finalise(config ++ Map('ontology -> ontology, 'data -> data))
114 }
115 case a => exit(s"Invalid sequence of arguments '${a.mkString(" ")}'.")
116 }
117 }
118
119 /** Perform final checks on parsed options */
120 private def finalise(config: Config): Config = config
121}
122 33
123/** Main entry point to the program */ 34/** Main entry point to the program */
124object RSAComb extends App { 35object RSAComb extends App {
@@ -126,42 +37,52 @@ object RSAComb extends App {
126 /* Command-line options */ 37 /* Command-line options */
127 val config = RSAConfig.parse(args.toList) 38 val config = RSAConfig.parse(args.toList)
128 39
40 /* Set logger level */
41 if (config.contains('logger))
42 Logger.level = config('logger).get[Logger.Level]
43
129 /* Load original ontology and normalize it */ 44 /* Load original ontology and normalize it */
130 val ontology = Ontology( 45 val ontology = Ontology(
131 config('ontology).get[File], 46 config('ontology).get[os.Path],
132 config('data).get[List[File]] 47 config('data).get[List[os.Path]]
133 ).normalize(new Normalizer) 48 ).normalize(new Normalizer)
134 49
50 //ontology.axioms foreach println
51
135 /* Approximate the ontology to RSA */ 52 /* Approximate the ontology to RSA */
136 val toRSA = new LowerBound 53 val toRSA = new Upperbound
137 val rsa = ontology approximate toRSA 54 val rsa = ontology approximate toRSA
138 55
139 if (config contains 'query) { 56 if (config contains 'queries) {
140 val query = 57 val queries =
141 RDFoxUtil.loadQueryFromFile(config('query).get[File].getAbsoluteFile) 58 RDFoxUtil.loadQueriesFromFile(
142 59 config('queries).get[os.Path]
143 ConjunctiveQuery.parse(query) match { 60 )
144 case Some(query) => { 61
145 // Retrieve answers 62 val answers = rsa ask queries
146 val answers = rsa ask query 63
147 Logger.print(s"$answers", Logger.VERBOSE) 64 /* Write answers to output file */
148 Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})" 65 if (config.contains('answers))
149 // Retrieve unfiltered answers 66 os.write(
150 // val unfiltered = rsa.queryDataStore( 67 config('answers).get[os.Path],
151 // """ 68 ujson.write(ujson.Arr(answers.map(_.toJSON)), indent = 4),
152 // SELECT (count(?K) as ?COUNT) 69 createFolders = true
153 // WHERE { 70 )
154 // ?K a rsa:QM . 71
155 // } 72 // Logger.print(s"$answers", Logger.VERBOSE)
156 // """, 73 // Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})"
157 // RSA.Prefixes 74 // Retrieve unfiltered answers
158 // ) 75 // val unfiltered = rsa.queryDataStore(
159 // unfiltered.foreach((u) => 76 // """
160 // Logger print s"Number of unfiltered answers: ${u.head._2}" 77 // SELECT (count(?K) as ?COUNT)
161 // ) 78 // WHERE {
162 } 79 // ?K a rsa:QM .
163 case None => 80 // }
164 throw new RuntimeException("Submitted query is not conjunctive") 81 // """,
165 } 82 // RSA.Prefixes
83 // )
84 // unfiltered.foreach((u) =>
85 // Logger print s"Number of unfiltered answers: ${u.head._2}"
86 // )
166 } 87 }
167} 88}