diff options
author | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-11-18 19:13:25 +0000 |
---|---|---|
committer | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-11-18 19:13:25 +0000 |
commit | 1efc189e90240c162b54cbc50362b46786643dad (patch) | |
tree | 9beabe0a2af7ba1674aea0060787782aa72e8a83 /src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala | |
parent | a45aeff72b82bbc9a52f10929bf15b414c868525 (diff) | |
download | RSAComb-1efc189e90240c162b54cbc50362b46786643dad.tar.gz RSAComb-1efc189e90240c162b54cbc50362b46786643dad.zip |
Reorganize project with Java-like folder structure
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.scala | 249 |
1 files changed, 249 insertions, 0 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 new file mode 100644 index 0000000..c3db99d --- /dev/null +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala | |||
@@ -0,0 +1,249 @@ | |||
1 | package uk.ac.ox.cs.rsacomb | ||
2 | |||
3 | /* Java imports */ | ||
4 | import java.io.File | ||
5 | import java.util.HashMap | ||
6 | import scala.collection.JavaConverters._ | ||
7 | |||
8 | import tech.oxfordsemantic.jrdfox.client.UpdateType | ||
9 | import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery | ||
10 | import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term} | ||
11 | |||
12 | /* Local imports */ | ||
13 | import util.{RDFoxHelpers, RSA} | ||
14 | |||
15 | object RSAComb extends App { | ||
16 | |||
17 | val help: String = """ | ||
18 | rsacomb - combined approach for CQ answering for RSA ontologies. | ||
19 | |||
20 | USAGE | ||
21 | rsacomb <path/to/ontology.owl> <path/to/query.sparql> | ||
22 | |||
23 | where | ||
24 | the ontology is expected to be an OWL file and the (single) | ||
25 | query a SPARQL query file. | ||
26 | |||
27 | """ | ||
28 | |||
29 | /* Simple arguments handling | ||
30 | * | ||
31 | * TODO: use something better later on | ||
32 | */ | ||
33 | |||
34 | if (args.length < 2) { | ||
35 | println(help) | ||
36 | sys.exit; | ||
37 | } | ||
38 | |||
39 | val ontoPath = new File(args(0)) | ||
40 | val queryPath = new File(args(1)) | ||
41 | |||
42 | if (!ontoPath.isFile || !queryPath.isFile) { | ||
43 | println("The provided arguments are not regular files.\n\n") | ||
44 | println(help) | ||
45 | sys.exit; | ||
46 | } | ||
47 | |||
48 | /* Create RSA object from generic OWLOntology | ||
49 | * | ||
50 | * TODO: It might be required to check if the ontology in input is | ||
51 | * Horn-ALCHOIQ. At the moment we are assuming this is always the | ||
52 | * case. | ||
53 | */ | ||
54 | |||
55 | val ontology = RSAOntology(ontoPath) | ||
56 | if (ontology.isRSA) { | ||
57 | |||
58 | /* Load query */ | ||
59 | val query = RDFoxHelpers.parseSelectQuery( | ||
60 | """ | ||
61 | PREFIX : <http://example.com/rsa_example.owl#> | ||
62 | |||
63 | SELECT ?X | ||
64 | WHERE { | ||
65 | ?X a :D ; | ||
66 | :R ?Y . | ||
67 | ?Y :S ?Z . | ||
68 | ?Z a :D . | ||
69 | } | ||
70 | """ | ||
71 | ) | ||
72 | |||
73 | /* Compute answers to query */ | ||
74 | query match { | ||
75 | case Some(query) => { | ||
76 | |||
77 | import implicits.JavaCollections._ | ||
78 | |||
79 | // Open connection to RDFox | ||
80 | val (server, data) = RDFoxHelpers.openConnection("AnswerComputation") | ||
81 | |||
82 | { | ||
83 | println("\nQuery") | ||
84 | println(query) | ||
85 | } | ||
86 | |||
87 | // Step 1. Computing the canonical model | ||
88 | val canon = ontology.canonicalModel | ||
89 | data.addRules(canon.rules) | ||
90 | |||
91 | { | ||
92 | println("\nCanonical Model rules:") | ||
93 | canon.rules.foreach(println) | ||
94 | } | ||
95 | |||
96 | // Step 2. Computing the canonical model | ||
97 | val nis = { | ||
98 | val query = "SELECT ?Y WHERE { ?X rsa:EquivTo ?Y ; a rsa:Named . }" | ||
99 | RDFoxHelpers.submitSelectQuery(data, query, RSA.Prefixes).flatten | ||
100 | } | ||
101 | val filter = ontology.filteringProgram(query, nis) | ||
102 | data.addRules(filter.rules) | ||
103 | |||
104 | { | ||
105 | println("\nFiltering rules") | ||
106 | filter.rules.foreach(println) | ||
107 | } | ||
108 | |||
109 | // Retrieve answers | ||
110 | println("\nAnswers:") | ||
111 | val ans = | ||
112 | RDFoxHelpers.queryInternalPredicate(data, "Ans", filter.answer.length) | ||
113 | println(ans) | ||
114 | |||
115 | /* DEBUG: adding additional checks | ||
116 | */ | ||
117 | { | ||
118 | import suffix.{Forward, Backward} | ||
119 | |||
120 | val arity = filter.answer.length + filter.bounded.length | ||
121 | |||
122 | println("\nIndividuals:") | ||
123 | ontology.individuals.foreach(println) | ||
124 | |||
125 | println("\nThings:") | ||
126 | val things = RDFoxHelpers.submitSelectQuery( | ||
127 | data, | ||
128 | """ | ||
129 | PREFIX owl: <http://www.w3.org/2002/07/owl#> | ||
130 | |||
131 | SELECT ?X { | ||
132 | ?X a owl:Thing | ||
133 | } | ||
134 | """ | ||
135 | ) | ||
136 | println(things) | ||
137 | |||
138 | println("\nNAMEDs:") | ||
139 | val named = RDFoxHelpers.submitSelectQuery( | ||
140 | data, | ||
141 | """ | ||
142 | SELECT ?X { | ||
143 | ?X a rsa:Named | ||
144 | } | ||
145 | """, | ||
146 | RSA.Prefixes | ||
147 | ) | ||
148 | println(named) | ||
149 | |||
150 | println("\nNIs:") | ||
151 | val nis = RDFoxHelpers.submitSelectQuery( | ||
152 | data, | ||
153 | """ | ||
154 | SELECT ?X { | ||
155 | ?X a rsa:NI | ||
156 | } | ||
157 | """, | ||
158 | RSA.Prefixes | ||
159 | ) | ||
160 | println(nis) | ||
161 | |||
162 | // ID instances | ||
163 | println("\nIDs:") | ||
164 | val ids = RDFoxHelpers.queryInternalPredicate( | ||
165 | data, | ||
166 | "ID", | ||
167 | arity + 2 | ||
168 | ) | ||
169 | println(ids) | ||
170 | |||
171 | println("\nEquivTo:") | ||
172 | val equivs = RDFoxHelpers.submitSelectQuery( | ||
173 | data, | ||
174 | """ | ||
175 | SELECT ?X ?Y { | ||
176 | ?X rsa:EquivTo ?Y | ||
177 | } | ||
178 | """, | ||
179 | RSA.Prefixes | ||
180 | ) | ||
181 | println(equivs) | ||
182 | |||
183 | // Unfiltered answers | ||
184 | println("\nPossible answers:") | ||
185 | val qms = RDFoxHelpers.queryInternalPredicate( | ||
186 | data, | ||
187 | "QM", | ||
188 | arity | ||
189 | ) | ||
190 | println(qms) | ||
191 | |||
192 | // Cycle detected | ||
193 | println("\nCycle detection:") | ||
194 | val aqf = RDFoxHelpers.queryInternalPredicate( | ||
195 | data, | ||
196 | "AQ" :: Forward, | ||
197 | arity + 2 | ||
198 | ) | ||
199 | val aqb = RDFoxHelpers.queryInternalPredicate( | ||
200 | data, | ||
201 | "AQ" :: Backward, | ||
202 | arity + 2 | ||
203 | ) | ||
204 | println(aqf) | ||
205 | println(aqb) | ||
206 | |||
207 | // Forks detected | ||
208 | println("\nForks:") | ||
209 | val fk = RDFoxHelpers.queryInternalPredicate( | ||
210 | data, | ||
211 | "FK", | ||
212 | arity | ||
213 | ) | ||
214 | println(fk) | ||
215 | |||
216 | // Spurious answers | ||
217 | println("\nSpurious answers") | ||
218 | val sp = RDFoxHelpers.queryInternalPredicate( | ||
219 | data, | ||
220 | "SP", | ||
221 | arity | ||
222 | ) | ||
223 | println(sp) | ||
224 | } | ||
225 | |||
226 | // Close connection to RDFox | ||
227 | RDFoxHelpers.closeConnection(server, data) | ||
228 | } | ||
229 | case None => {} | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | |||
234 | /* Notes: | ||
235 | * | ||
236 | * To establish a connection with a local RDFox instance, do the | ||
237 | * following: | ||
238 | * | ||
239 | * ``` | ||
240 | * val serverConnection : ServerConnection = ConnectionFactory.newServerConnection("rdfox:local", "", "") | ||
241 | * serverConnection.createDataStore("test","seq",new HashMap()) | ||
242 | * val dataStoreConnection : DataStoreConnection = serverConnection.newDataStoreConnection("test") | ||
243 | * dataStoreConnection.importData( | ||
244 | * UpdateType.ADDITION, | ||
245 | * Prefixes.s_emptyPrefixes, | ||
246 | * new File("./path/to/file") | ||
247 | * ) | ||
248 | * ``` | ||
249 | */ | ||