Mercurial > hg > svcore
comparison rdf/RDFTransformFactory.cpp @ 489:82ab61fa9223
* Reorganise our sparql queries on the basis that Redland must be
available, not only optional. So for anything querying the pool
of data about plugins, we use a single datastore and model which
is initialised at the outset by PluginRDFIndexer and then queried
directly; for anything that "reads from a file" (e.g. loading
annotations) we query directly using Rasqal, going to the
datastore when we need additional plugin-related information.
This may improve performance, but mostly it simplifies the code
and fixes a serious issue with RDF import in the previous versions
(namely that multiple sequential RDF imports would end up sharing
the same RDF data pool!)
author | Chris Cannam |
---|---|
date | Fri, 21 Nov 2008 16:12:29 +0000 |
parents | 3ffce691c9bf |
children | 23945cdd7161 |
comparison
equal
deleted
inserted
replaced
488:1c66e199e7d9 | 489:82ab61fa9223 |
---|---|
45 std::vector<Transform> getTransforms(ProgressReporter *); | 45 std::vector<Transform> getTransforms(ProgressReporter *); |
46 | 46 |
47 protected: | 47 protected: |
48 QString m_urlString; | 48 QString m_urlString; |
49 QString m_errorString; | 49 QString m_errorString; |
50 bool setOutput(Transform &, QString, QString); | 50 bool setOutput(Transform &, QString); |
51 bool setParameters(Transform &, QString, QString); | 51 bool setParameters(Transform &, QString); |
52 }; | 52 }; |
53 | 53 |
54 | 54 |
55 QString | 55 QString |
56 RDFTransformFactory::getKnownExtensions() | 56 RDFTransformFactory::getKnownExtensions() |
110 std::vector<Transform> | 110 std::vector<Transform> |
111 RDFTransformFactoryImpl::getTransforms(ProgressReporter *reporter) | 111 RDFTransformFactoryImpl::getTransforms(ProgressReporter *reporter) |
112 { | 112 { |
113 std::vector<Transform> transforms; | 113 std::vector<Transform> transforms; |
114 | 114 |
115 // We have to do this a very long way round, to work around | |
116 // rasqal's current inability to handle correctly more than one | |
117 // OPTIONAL graph in a query | |
118 | |
119 const char *optionals[] = { | |
120 "output", | |
121 "program", | |
122 "step_size", | |
123 "block_size", | |
124 "window_type", | |
125 "sample_rate", | |
126 "start", | |
127 "duration" | |
128 }; | |
129 | |
130 std::map<QString, Transform> uriTransformMap; | 115 std::map<QString, Transform> uriTransformMap; |
131 | 116 |
132 QString queryTemplate = | 117 QString query = |
133 " PREFIX vamp: <http://purl.org/ontology/vamp/> " | 118 " PREFIX vamp: <http://purl.org/ontology/vamp/> " |
134 | 119 |
135 " SELECT ?transform ?plugin %1 " | 120 " SELECT ?transform ?plugin " |
136 | 121 |
137 " FROM <%2> " | 122 " FROM <%2> " |
138 | 123 |
139 " WHERE { " | 124 " WHERE { " |
140 " ?transform a vamp:Transform ; " | 125 " ?transform a vamp:Transform ; " |
141 " vamp:plugin ?plugin . " | 126 " vamp:plugin ?plugin . " |
142 " %3 " | |
143 " } "; | 127 " } "; |
144 | 128 |
145 SimpleSPARQLQuery transformsQuery | 129 SimpleSPARQLQuery transformsQuery |
146 (m_urlString, queryTemplate.arg("").arg(m_urlString).arg("")); | 130 (SimpleSPARQLQuery::QueryFromSingleSource, query.arg(m_urlString)); |
147 | 131 |
148 SimpleSPARQLQuery::ResultList transformResults = transformsQuery.execute(); | 132 SimpleSPARQLQuery::ResultList transformResults = transformsQuery.execute(); |
149 | 133 |
150 if (!transformsQuery.isOK()) { | 134 if (!transformsQuery.isOK()) { |
151 m_errorString = transformsQuery.getErrorString(); | 135 m_errorString = transformsQuery.getErrorString(); |
154 | 138 |
155 if (transformResults.empty()) { | 139 if (transformResults.empty()) { |
156 cerr << "RDFTransformFactory: NOTE: No RDF/TTL transform descriptions found in document at <" << m_urlString.toStdString() << ">" << endl; | 140 cerr << "RDFTransformFactory: NOTE: No RDF/TTL transform descriptions found in document at <" << m_urlString.toStdString() << ">" << endl; |
157 return transforms; | 141 return transforms; |
158 } | 142 } |
143 | |
144 // There are various queries we need to make that might include | |
145 // data from iether the transform RDF or the model accumulated | |
146 // from plugin descriptions. For example, the transform RDF may | |
147 // specify the output's true URI, or it might have a blank node or | |
148 // some other URI with the appropriate vamp:identifier included in | |
149 // the file. To cover both cases, we need to add the file itself | |
150 // into the model and always query the model using the transform | |
151 // URI rather than querying the file itself subsequently. | |
152 | |
153 SimpleSPARQLQuery::addSourceToModel(m_urlString); | |
159 | 154 |
160 PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance(); | 155 PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance(); |
161 | 156 |
162 for (int i = 0; i < transformResults.size(); ++i) { | 157 for (int i = 0; i < transformResults.size(); ++i) { |
163 | 158 |
173 << transformUri.toStdString() << ">, skipping this transform" | 168 << transformUri.toStdString() << ">, skipping this transform" |
174 << endl; | 169 << endl; |
175 continue; | 170 continue; |
176 } | 171 } |
177 | 172 |
178 QString pluginDescriptionURL = | |
179 indexer->getDescriptionURLForPluginId(pluginId); | |
180 if (pluginDescriptionURL == "") { | |
181 cerr << "RDFTransformFactory: WARNING: No RDF description available for plugin <" | |
182 << pluginUri.toStdString() << ">, skipping transform <" | |
183 << transformUri.toStdString() << ">" << endl; | |
184 continue; | |
185 } | |
186 | |
187 Transform transform; | 173 Transform transform; |
188 transform.setPluginIdentifier(pluginId); | 174 transform.setPluginIdentifier(pluginId); |
189 | 175 |
190 if (!setOutput(transform, transformUri, pluginDescriptionURL)) { | 176 if (!setOutput(transform, transformUri)) { |
191 return transforms; | 177 return transforms; |
192 } | 178 } |
193 | 179 |
194 if (!setParameters(transform, transformUri, pluginDescriptionURL)) { | 180 if (!setParameters(transform, transformUri)) { |
195 return transforms; | 181 return transforms; |
196 } | 182 } |
197 | 183 |
198 uriTransformMap[transformUri] = transform; | 184 uriTransformMap[transformUri] = transform; |
199 } | 185 |
200 | 186 // We have to do this a very long way round, to work around |
201 for (int i = 0; i < sizeof(optionals)/sizeof(optionals[0]); ++i) { | 187 // rasqal's current inability to handle correctly more than one |
202 | 188 // OPTIONAL graph in a query |
203 QString optional = optionals[i]; | 189 |
204 | 190 static const char *optionals[] = { |
205 SimpleSPARQLQuery query | 191 "output", |
206 (m_urlString, | 192 "program", |
207 queryTemplate | 193 "step_size", |
208 .arg(QString("?%1").arg(optional)) | 194 "block_size", |
209 .arg(m_urlString) | 195 "window_type", |
210 .arg(QString("?transform vamp:%1 ?%2") | 196 "sample_rate", |
211 .arg(optionals[i]).arg(optional))); | 197 "start", |
212 | 198 "duration" |
213 SimpleSPARQLQuery::ResultList results = query.execute(); | 199 }; |
214 | 200 |
215 if (!query.isOK()) { | 201 for (int j = 0; j < sizeof(optionals)/sizeof(optionals[0]); ++j) { |
216 m_errorString = query.getErrorString(); | 202 |
217 return transforms; | 203 QString optional = optionals[j]; |
218 } | 204 |
219 | 205 QString queryTemplate = |
220 if (results.empty()) continue; | 206 " PREFIX vamp: <http://purl.org/ontology/vamp/> " |
221 | 207 |
222 for (int j = 0; j < results.size(); ++j) { | 208 " SELECT ?%1 " |
223 | 209 |
224 QString transformUri = results[j]["transform"].value; | 210 " WHERE { " |
211 " <%2> vamp:%1 ?%1 " | |
212 " } "; | |
225 | 213 |
226 if (uriTransformMap.find(transformUri) == uriTransformMap.end()) { | 214 SimpleSPARQLQuery query |
227 cerr << "RDFTransformFactory: ERROR: Transform URI <" | 215 (SimpleSPARQLQuery::QueryFromModel, |
228 << transformUri.toStdString() << "> not found in internal map!" << endl; | 216 queryTemplate.arg(optional).arg(transformUri)); |
229 continue; | 217 |
218 SimpleSPARQLQuery::ResultList results = query.execute(); | |
219 | |
220 if (!query.isOK()) { | |
221 m_errorString = query.getErrorString(); | |
222 return transforms; | |
230 } | 223 } |
231 | 224 |
232 Transform &transform = uriTransformMap[transformUri]; | 225 if (results.empty()) continue; |
233 const SimpleSPARQLQuery::Value &v = results[j][optional]; | 226 |
234 | 227 for (int k = 0; k < results.size(); ++k) { |
235 if (v.type == SimpleSPARQLQuery::LiteralValue) { | 228 |
229 const SimpleSPARQLQuery::Value &v = results[k][optional]; | |
230 | |
231 if (v.type == SimpleSPARQLQuery::LiteralValue) { | |
236 | 232 |
237 if (optional == "program") { | 233 if (optional == "program") { |
238 transform.setProgram(v.value); | 234 transform.setProgram(v.value); |
239 } else if (optional == "step_size") { | 235 } else if (optional == "step_size") { |
240 transform.setStepSize(v.value.toUInt()); | 236 transform.setStepSize(v.value.toUInt()); |
241 } else if (optional == "block_size") { | 237 } else if (optional == "block_size") { |
242 transform.setBlockSize(v.value.toUInt()); | 238 transform.setBlockSize(v.value.toUInt()); |
243 } else if (optional == "window_type") { | 239 } else if (optional == "window_type") { |
244 cerr << "NOTE: can't handle window type yet (value is \"" | 240 cerr << "NOTE: can't handle window type yet (value is \"" |
245 << v.value.toStdString() << "\")" << endl; | 241 << v.value.toStdString() << "\")" << endl; |
246 } else if (optional == "sample_rate") { | 242 } else if (optional == "sample_rate") { |
247 transform.setSampleRate(v.value.toFloat()); | 243 transform.setSampleRate(v.value.toFloat()); |
248 } else if (optional == "start") { | 244 } else if (optional == "start") { |
249 transform.setStartTime | 245 transform.setStartTime |
250 (RealTime::fromXsdDuration(v.value.toStdString())); | 246 (RealTime::fromXsdDuration(v.value.toStdString())); |
251 } else if (optional == "duration") { | 247 } else if (optional == "duration") { |
252 transform.setDuration | 248 transform.setDuration |
253 (RealTime::fromXsdDuration(v.value.toStdString())); | 249 (RealTime::fromXsdDuration(v.value.toStdString())); |
254 } else { | 250 } else { |
255 cerr << "RDFTransformFactory: ERROR: Inconsistent optionals lists (unexpected optional \"" << optional.toStdString() << "\"" << endl; | 251 cerr << "RDFTransformFactory: ERROR: Inconsistent optionals lists (unexpected optional \"" << optional.toStdString() << "\"" << endl; |
252 } | |
256 } | 253 } |
257 } | 254 } |
258 } | 255 } |
259 } | |
260 | |
261 for (std::map<QString, Transform>::iterator i = uriTransformMap.begin(); | |
262 i != uriTransformMap.end(); ++i) { | |
263 | |
264 Transform &transform = i->second; | |
265 | 256 |
266 cerr << "RDFTransformFactory: NOTE: Transform is: " << endl; | 257 cerr << "RDFTransformFactory: NOTE: Transform is: " << endl; |
267 cerr << transform.toXmlString().toStdString() << endl; | 258 cerr << transform.toXmlString().toStdString() << endl; |
268 | 259 |
269 transforms.push_back(transform); | 260 transforms.push_back(transform); |
272 return transforms; | 263 return transforms; |
273 } | 264 } |
274 | 265 |
275 bool | 266 bool |
276 RDFTransformFactoryImpl::setOutput(Transform &transform, | 267 RDFTransformFactoryImpl::setOutput(Transform &transform, |
277 QString transformUri, | 268 QString transformUri) |
278 QString pluginDescriptionURL) | 269 { |
279 { | 270 SimpleSPARQLQuery::Value outputValue = |
280 SimpleSPARQLQuery outputQuery | 271 SimpleSPARQLQuery::singleResultQuery |
281 (m_urlString, | 272 (SimpleSPARQLQuery::QueryFromModel, |
282 QString | 273 QString |
283 ( | 274 ( |
284 " PREFIX vamp: <http://purl.org/ontology/vamp/> " | 275 " PREFIX vamp: <http://purl.org/ontology/vamp/> " |
285 | 276 |
286 " SELECT ?output_id " | 277 " SELECT ?output " |
287 | 278 |
288 " FROM <%1> " | |
289 " FROM <%2> " | |
290 | |
291 " WHERE { " | 279 " WHERE { " |
292 " <%3> vamp:output ?output . " | 280 " <%1> vamp:output ?output . " |
293 " ?output vamp:identifier ?output_id " | |
294 " } " | 281 " } " |
295 ) | 282 ) |
296 .arg(m_urlString) | 283 .arg(transformUri), |
297 .arg(pluginDescriptionURL) | 284 "output"); |
298 .arg(transformUri)); | 285 |
299 | 286 if (outputValue.type == SimpleSPARQLQuery::NoValue) { |
300 SimpleSPARQLQuery::ResultList outputResults = outputQuery.execute(); | 287 return true; |
301 | 288 } |
302 if (!outputQuery.isOK()) { | 289 |
303 m_errorString = outputQuery.getErrorString(); | 290 if (outputValue.type != SimpleSPARQLQuery::URIValue) { |
291 m_errorString = "No vamp:output given, or not a URI"; | |
304 return false; | 292 return false; |
305 } | 293 } |
306 | 294 |
307 if (outputQuery.wasCancelled()) { | 295 SimpleSPARQLQuery::Value outputIdValue = |
308 m_errorString = "Query cancelled"; | 296 SimpleSPARQLQuery::singleResultQuery |
309 return false; | 297 (SimpleSPARQLQuery::QueryFromModel, |
310 } | |
311 | |
312 for (int j = 0; j < outputResults.size(); ++j) { | |
313 QString outputId = outputResults[j]["output_id"].value; | |
314 transform.setOutput(outputId); | |
315 } | |
316 | |
317 return true; | |
318 } | |
319 | |
320 | |
321 bool | |
322 RDFTransformFactoryImpl::setParameters(Transform &transform, | |
323 QString transformUri, | |
324 QString pluginDescriptionURL) | |
325 { | |
326 SimpleSPARQLQuery paramQuery | |
327 (m_urlString, | |
328 QString | 298 QString |
329 ( | 299 ( |
330 " PREFIX vamp: <http://purl.org/ontology/vamp/> " | 300 " PREFIX vamp: <http://purl.org/ontology/vamp/> " |
331 | 301 |
302 " SELECT ?output_id " | |
303 | |
304 " WHERE { " | |
305 " <%1> vamp:identifier ?output_id " | |
306 " } " | |
307 ) | |
308 .arg(outputValue.value), | |
309 "output_id"); | |
310 | |
311 if (outputIdValue.type != SimpleSPARQLQuery::LiteralValue) { | |
312 m_errorString = "No output vamp:identifier available, or not a literal"; | |
313 return false; | |
314 } | |
315 | |
316 transform.setOutput(outputIdValue.value); | |
317 | |
318 return true; | |
319 } | |
320 | |
321 | |
322 bool | |
323 RDFTransformFactoryImpl::setParameters(Transform &transform, | |
324 QString transformUri) | |
325 { | |
326 SimpleSPARQLQuery paramQuery | |
327 (SimpleSPARQLQuery::QueryFromModel, | |
328 QString | |
329 ( | |
330 " PREFIX vamp: <http://purl.org/ontology/vamp/> " | |
331 | |
332 " SELECT ?param_id ?param_value " | 332 " SELECT ?param_id ?param_value " |
333 | 333 |
334 " FROM <%1> " | |
335 " FROM <%2> " | |
336 | |
337 " WHERE { " | 334 " WHERE { " |
338 " <%3> vamp:parameter_binding ?binding . " | 335 " <%1> vamp:parameter_binding ?binding . " |
339 " ?binding vamp:parameter ?param ; " | 336 " ?binding vamp:parameter ?param ; " |
340 " vamp:value ?param_value . " | 337 " vamp:value ?param_value . " |
341 " ?param vamp:identifier ?param_id " | 338 " ?param vamp:identifier ?param_id " |
342 " } " | 339 " } " |
343 ) | 340 ) |
344 .arg(m_urlString) | |
345 .arg(pluginDescriptionURL) | |
346 .arg(transformUri)); | 341 .arg(transformUri)); |
347 | 342 |
348 SimpleSPARQLQuery::ResultList paramResults = paramQuery.execute(); | 343 SimpleSPARQLQuery::ResultList paramResults = paramQuery.execute(); |
349 | 344 |
350 if (!paramQuery.isOK()) { | 345 if (!paramQuery.isOK()) { |