annotate rdf/PluginRDFDescription.cpp @ 481:a82645e788fc

* Auto-select RDF datastore/parsing backend; use trees datastore if available * Make CachedFile remember whether a file has already been successfully located locally (avoiding system call out to look at filesystem)
author Chris Cannam
date Fri, 14 Nov 2008 10:10:05 +0000
parents 3ffce691c9bf
children 82ab61fa9223
rev   line source
Chris@439 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@439 2
Chris@439 3 /*
Chris@439 4 Sonic Visualiser
Chris@439 5 An audio file viewer and annotation editor.
Chris@439 6 Centre for Digital Music, Queen Mary, University of London.
Chris@439 7 This file copyright 2008 QMUL.
Chris@439 8
Chris@439 9 This program is free software; you can redistribute it and/or
Chris@439 10 modify it under the terms of the GNU General Public License as
Chris@439 11 published by the Free Software Foundation; either version 2 of the
Chris@439 12 License, or (at your option) any later version. See the file
Chris@439 13 COPYING included with this distribution for more information.
Chris@439 14 */
Chris@439 15
Chris@439 16 #include "PluginRDFDescription.h"
Chris@439 17
Chris@439 18 #include "PluginRDFIndexer.h"
Chris@439 19 #include "SimpleSPARQLQuery.h"
Chris@439 20
Chris@457 21 #include "data/fileio/FileSource.h"
Chris@468 22 #include "data/fileio/CachedFile.h"
Chris@457 23
Chris@457 24 #include "base/Profiler.h"
Chris@457 25
Chris@439 26 #include "plugin/PluginIdentifier.h"
Chris@439 27
Chris@439 28 #include <iostream>
Chris@439 29 using std::cerr;
Chris@439 30 using std::endl;
Chris@439 31
Chris@439 32 PluginRDFDescription::PluginRDFDescription(QString pluginId) :
Chris@439 33 m_pluginId(pluginId),
Chris@439 34 m_haveDescription(false)
Chris@439 35 {
Chris@439 36 PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
Chris@439 37 QString url = indexer->getDescriptionURLForPluginId(pluginId);
Chris@439 38 if (url == "") {
Chris@439 39 cerr << "PluginRDFDescription: WARNING: No RDF description available for plugin ID \""
Chris@439 40 << pluginId.toStdString() << "\"" << endl;
Chris@439 41 } else {
Chris@439 42 if (!indexURL(url)) {
Chris@439 43 cerr << "PluginRDFDescription: ERROR: Failed to query RDF description for plugin ID \""
Chris@439 44 << pluginId.toStdString() << "\"" << endl;
Chris@439 45 } else {
Chris@439 46 m_haveDescription = true;
Chris@439 47 }
Chris@439 48 }
Chris@439 49 }
Chris@439 50
Chris@439 51 PluginRDFDescription::~PluginRDFDescription()
Chris@439 52 {
Chris@439 53 }
Chris@439 54
Chris@439 55 bool
Chris@439 56 PluginRDFDescription::haveDescription() const
Chris@439 57 {
Chris@439 58 return m_haveDescription;
Chris@439 59 }
Chris@439 60
Chris@457 61 QString
Chris@457 62 PluginRDFDescription::getPluginName() const
Chris@457 63 {
Chris@457 64 return m_pluginName;
Chris@457 65 }
Chris@457 66
Chris@457 67 QString
Chris@457 68 PluginRDFDescription::getPluginDescription() const
Chris@457 69 {
Chris@457 70 return m_pluginDescription;
Chris@457 71 }
Chris@457 72
Chris@457 73 QString
Chris@457 74 PluginRDFDescription::getPluginMaker() const
Chris@457 75 {
Chris@457 76 return m_pluginMaker;
Chris@457 77 }
Chris@457 78
Chris@462 79 QString
Chris@462 80 PluginRDFDescription::getPluginInfoURL() const
Chris@462 81 {
Chris@462 82 return m_pluginInfoURL;
Chris@462 83 }
Chris@462 84
Chris@457 85 QStringList
Chris@457 86 PluginRDFDescription::getOutputIds() const
Chris@457 87 {
Chris@457 88 QStringList ids;
Chris@457 89 for (OutputDispositionMap::const_iterator i = m_outputDispositions.begin();
Chris@457 90 i != m_outputDispositions.end(); ++i) {
Chris@457 91 ids.push_back(i->first);
Chris@457 92 }
Chris@457 93 return ids;
Chris@457 94 }
Chris@457 95
Chris@457 96 QString
Chris@457 97 PluginRDFDescription::getOutputName(QString outputId) const
Chris@457 98 {
Chris@457 99 if (m_outputNames.find(outputId) == m_outputNames.end()) {
Chris@457 100 return "";
Chris@457 101 }
Chris@457 102 return m_outputNames.find(outputId)->second;
Chris@457 103 }
Chris@457 104
Chris@439 105 PluginRDFDescription::OutputDisposition
Chris@439 106 PluginRDFDescription::getOutputDisposition(QString outputId) const
Chris@439 107 {
Chris@439 108 if (m_outputDispositions.find(outputId) == m_outputDispositions.end()) {
Chris@439 109 return OutputDispositionUnknown;
Chris@439 110 }
Chris@439 111 return m_outputDispositions.find(outputId)->second;
Chris@439 112 }
Chris@439 113
Chris@439 114 QString
Chris@439 115 PluginRDFDescription::getOutputEventTypeURI(QString outputId) const
Chris@439 116 {
Chris@439 117 if (m_outputEventTypeURIMap.find(outputId) ==
Chris@439 118 m_outputEventTypeURIMap.end()) {
Chris@439 119 return "";
Chris@439 120 }
Chris@439 121 return m_outputEventTypeURIMap.find(outputId)->second;
Chris@439 122 }
Chris@439 123
Chris@439 124 QString
Chris@440 125 PluginRDFDescription::getOutputFeatureAttributeURI(QString outputId) const
Chris@440 126 {
Chris@440 127 if (m_outputFeatureAttributeURIMap.find(outputId) ==
Chris@440 128 m_outputFeatureAttributeURIMap.end()) {
Chris@440 129 return "";
Chris@440 130 }
Chris@440 131 return m_outputFeatureAttributeURIMap.find(outputId)->second;
Chris@440 132 }
Chris@440 133
Chris@440 134 QString
Chris@440 135 PluginRDFDescription::getOutputSignalTypeURI(QString outputId) const
Chris@440 136 {
Chris@440 137 if (m_outputSignalTypeURIMap.find(outputId) ==
Chris@440 138 m_outputSignalTypeURIMap.end()) {
Chris@440 139 return "";
Chris@440 140 }
Chris@440 141 return m_outputSignalTypeURIMap.find(outputId)->second;
Chris@440 142 }
Chris@440 143
Chris@440 144 QString
Chris@439 145 PluginRDFDescription::getOutputUnit(QString outputId) const
Chris@439 146 {
Chris@439 147 if (m_outputUnitMap.find(outputId) == m_outputUnitMap.end()) {
Chris@439 148 return "";
Chris@439 149 }
Chris@439 150 return m_outputUnitMap.find(outputId)->second;
Chris@439 151 }
Chris@439 152
Chris@439 153 bool
Chris@439 154 PluginRDFDescription::indexURL(QString url)
Chris@439 155 {
Chris@457 156 Profiler profiler("PluginRDFDescription::indexURL");
Chris@457 157
Chris@439 158 QString type, soname, label;
Chris@439 159 PluginIdentifier::parseIdentifier(m_pluginId, type, soname, label);
Chris@439 160
Chris@457 161 bool success = true;
Chris@457 162
Chris@457 163 QString local = url;
Chris@457 164
Chris@457 165 if (FileSource::isRemote(url) &&
Chris@457 166 FileSource::canHandleScheme(url)) {
Chris@461 167
Chris@468 168 CachedFile cf(url);
Chris@468 169 if (!cf.isOK()) {
Chris@468 170 return false;
Chris@468 171 }
Chris@468 172
Chris@468 173 local = QUrl::fromLocalFile(cf.getLocalFilename()).toString();
Chris@457 174 }
Chris@457 175
Chris@457 176 if (!indexMetadata(local, label)) success = false;
Chris@457 177 if (!indexOutputs(local, label)) success = false;
Chris@457 178
Chris@457 179 return success;
Chris@457 180 }
Chris@457 181
Chris@457 182 bool
Chris@457 183 PluginRDFDescription::indexMetadata(QString url, QString label)
Chris@457 184 {
Chris@457 185 Profiler profiler("PluginRDFDescription::indexMetadata");
Chris@457 186
Chris@457 187 QString queryTemplate =
Chris@457 188 QString(
Chris@457 189 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 190 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@457 191 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@457 192 " SELECT ?%4 FROM <%1> "
Chris@457 193 " WHERE { "
Chris@481 194 " ?plugin vamp:identifier \"%2\" ; "
Chris@481 195 " a vamp:Plugin ; "
Chris@457 196 " %3 ?%4 . "
Chris@457 197 " }")
Chris@457 198 .arg(url)
Chris@457 199 .arg(label);
Chris@457 200
Chris@457 201 SimpleSPARQLQuery::Value v;
Chris@457 202
Chris@457 203 v = SimpleSPARQLQuery::singleResultQuery
Chris@480 204 (url, queryTemplate.arg("vamp:name").arg("name"), "name");
Chris@457 205
Chris@457 206 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 207 m_pluginName = v.value;
Chris@457 208 }
Chris@457 209
Chris@457 210 v = SimpleSPARQLQuery::singleResultQuery
Chris@480 211 (url, queryTemplate.arg("dc:description").arg("description"), "description");
Chris@457 212
Chris@457 213 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 214 m_pluginDescription = v.value;
Chris@457 215 }
Chris@457 216
Chris@457 217 v = SimpleSPARQLQuery::singleResultQuery
Chris@480 218 (url,
Chris@480 219 QString(
Chris@457 220 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 221 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@457 222 " SELECT ?name FROM <%1> "
Chris@457 223 " WHERE { "
Chris@481 224 " ?plugin vamp:identifier \"%2\" ; "
Chris@481 225 " a vamp:Plugin ; "
Chris@457 226 " foaf:maker ?maker . "
Chris@457 227 " ?maker foaf:name ?name . "
Chris@457 228 " }")
Chris@457 229 .arg(url)
Chris@457 230 .arg(label), "name");
Chris@457 231
Chris@457 232 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 233 m_pluginMaker = v.value;
Chris@457 234 }
Chris@457 235
Chris@462 236 // If we have a more-information URL for this plugin, then we take
Chris@463 237 // that. Otherwise, a more-information URL for the plugin
Chris@462 238 // library would do nicely. Failing that, we could perhaps use
Chris@462 239 // any foaf:page URL at all that appears in the file -- but
Chris@462 240 // perhaps that would be unwise
Chris@462 241
Chris@462 242 v = SimpleSPARQLQuery::singleResultQuery
Chris@480 243 (url,
Chris@480 244 QString(
Chris@462 245 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@462 246 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@462 247 " SELECT ?page from <%1> "
Chris@462 248 " WHERE { "
Chris@481 249 " ?plugin vamp:identifier \"%2\" ; "
Chris@481 250 " a vamp:Plugin ; "
Chris@462 251 " foaf:page ?page . "
Chris@462 252 " }")
Chris@462 253 .arg(url)
Chris@462 254 .arg(label), "page");
Chris@462 255
Chris@462 256 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@462 257
Chris@462 258 m_pluginInfoURL = v.value;
Chris@462 259
Chris@462 260 } else {
Chris@462 261
Chris@462 262 v = SimpleSPARQLQuery::singleResultQuery
Chris@480 263 (url,
Chris@480 264 QString(
Chris@462 265 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@462 266 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@462 267 " SELECT ?page from <%1> "
Chris@462 268 " WHERE { "
Chris@462 269 " ?library a vamp:PluginLibrary ; "
Chris@462 270 " vamp:available_plugin ?plugin ; "
Chris@462 271 " foaf:page ?page . "
Chris@462 272 " ?plugin a vamp:Plugin ; "
Chris@462 273 " vamp:identifier \"%2\" . "
Chris@462 274 " }")
Chris@462 275 .arg(url)
Chris@462 276 .arg(label), "page");
Chris@462 277
Chris@462 278 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@462 279
Chris@462 280 m_pluginInfoURL = v.value;
Chris@462 281 }
Chris@462 282 }
Chris@462 283
Chris@457 284 return true;
Chris@457 285 }
Chris@457 286
Chris@457 287 bool
Chris@457 288 PluginRDFDescription::indexOutputs(QString url, QString label)
Chris@457 289 {
Chris@457 290 Profiler profiler("PluginRDFDescription::indexOutputs");
Chris@457 291
Chris@439 292 SimpleSPARQLQuery query
Chris@480 293 (url,
Chris@480 294 QString
Chris@439 295 (
Chris@439 296 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@439 297
Chris@440 298 " SELECT ?output ?output_id ?output_type ?unit "
Chris@439 299 " FROM <%1> "
Chris@439 300
Chris@439 301 " WHERE { "
Chris@439 302
Chris@481 303 " ?plugin vamp:identifier \"%2\" ; "
Chris@481 304 " a vamp:Plugin ; "
Chris@440 305 " vamp:output ?output . "
Chris@439 306
Chris@439 307 " ?output vamp:identifier ?output_id ; "
Chris@439 308 " a ?output_type . "
Chris@439 309
Chris@439 310 " OPTIONAL { "
Chris@439 311 " ?output vamp:unit ?unit "
Chris@439 312 " } . "
Chris@439 313
Chris@439 314 " } "
Chris@439 315 )
Chris@439 316 .arg(url)
Chris@439 317 .arg(label));
Chris@439 318
Chris@439 319 SimpleSPARQLQuery::ResultList results = query.execute();
Chris@439 320
Chris@439 321 if (!query.isOK()) {
Chris@439 322 cerr << "ERROR: PluginRDFDescription::indexURL: ERROR: Failed to query document at <"
Chris@439 323 << url.toStdString() << ">: "
Chris@439 324 << query.getErrorString().toStdString() << endl;
Chris@439 325 return false;
Chris@439 326 }
Chris@439 327
Chris@439 328 if (results.empty()) {
Chris@439 329 cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: Document at <"
Chris@439 330 << url.toStdString()
Chris@440 331 << "> does not appear to describe any outputs for plugin with id \""
Chris@440 332 << label.toStdString() << "\"" << endl;
Chris@439 333 return false;
Chris@439 334 }
Chris@439 335
Chris@439 336 // Note that an output may appear more than once, if it inherits
Chris@439 337 // more than one type (e.g. DenseOutput and QuantizedOutput). So
Chris@439 338 // these results must accumulate
Chris@439 339
Chris@439 340 for (int i = 0; i < results.size(); ++i) {
Chris@439 341
Chris@440 342 QString outputUri = results[i]["output"].value;
Chris@439 343 QString outputId = results[i]["output_id"].value;
Chris@439 344 QString outputType = results[i]["output_type"].value;
Chris@439 345
Chris@439 346 if (outputType.contains("DenseOutput")) {
Chris@439 347 m_outputDispositions[outputId] = OutputDense;
Chris@439 348 } else if (outputType.contains("SparseOutput")) {
Chris@439 349 m_outputDispositions[outputId] = OutputSparse;
Chris@439 350 } else if (outputType.contains("TrackLevelOutput")) {
Chris@439 351 m_outputDispositions[outputId] = OutputTrackLevel;
Chris@457 352 } else {
Chris@457 353 m_outputDispositions[outputId] = OutputDispositionUnknown;
Chris@439 354 }
Chris@439 355
Chris@439 356 if (results[i]["unit"].type == SimpleSPARQLQuery::LiteralValue) {
Chris@439 357
Chris@439 358 QString unit = results[i]["unit"].value;
Chris@439 359
Chris@439 360 if (unit != "") {
Chris@439 361 m_outputUnitMap[outputId] = unit;
Chris@439 362 }
Chris@439 363 }
Chris@440 364
Chris@457 365 SimpleSPARQLQuery::Value v;
Chris@457 366
Chris@457 367 v = SimpleSPARQLQuery::singleResultQuery
Chris@480 368 (url,
Chris@480 369 QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 370 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@457 371 " SELECT ?title FROM <%1> "
Chris@457 372 " WHERE { <%2> dc:title ?title } ")
Chris@457 373 .arg(url).arg(outputUri), "title");
Chris@457 374
Chris@457 375 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 376 m_outputNames[outputId] = v.value;
Chris@457 377 }
Chris@457 378
Chris@440 379 QString queryTemplate =
Chris@440 380 QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@440 381 " SELECT ?%3 FROM <%1> "
Chris@440 382 " WHERE { <%2> vamp:computes_%3 ?%3 } ")
Chris@440 383 .arg(url).arg(outputUri);
Chris@440 384
Chris@440 385 v = SimpleSPARQLQuery::singleResultQuery
Chris@480 386 (url, queryTemplate.arg("event_type"), "event_type");
Chris@440 387
Chris@440 388 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 389 m_outputEventTypeURIMap[outputId] = v.value;
Chris@440 390 }
Chris@440 391
Chris@440 392 v = SimpleSPARQLQuery::singleResultQuery
Chris@480 393 (url, queryTemplate.arg("feature_attribute"), "feature_attribute");
Chris@440 394
Chris@440 395 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 396 m_outputFeatureAttributeURIMap[outputId] = v.value;
Chris@440 397 }
Chris@440 398
Chris@440 399 v = SimpleSPARQLQuery::singleResultQuery
Chris@480 400 (url, queryTemplate.arg("signal_type"), "signal_type");
Chris@440 401
Chris@440 402 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 403 m_outputSignalTypeURIMap[outputId] = v.value;
Chris@440 404 }
Chris@439 405 }
Chris@439 406
Chris@439 407 return true;
Chris@439 408 }
Chris@439 409