annotate rdf/PluginRDFDescription.cpp @ 468:70b333085952

* complete switching the code to use CachedFile -- now to tidy & fix the remaining flaws...
author Chris Cannam
date Mon, 27 Oct 2008 20:29:55 +0000
parents 93806ad9481e
children 0dc158c1a6c9
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@468 33 //!!! m_source(0),
Chris@439 34 m_pluginId(pluginId),
Chris@439 35 m_haveDescription(false)
Chris@439 36 {
Chris@439 37 PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
Chris@439 38 QString url = indexer->getDescriptionURLForPluginId(pluginId);
Chris@439 39 if (url == "") {
Chris@439 40 cerr << "PluginRDFDescription: WARNING: No RDF description available for plugin ID \""
Chris@439 41 << pluginId.toStdString() << "\"" << endl;
Chris@439 42 } else {
Chris@439 43 if (!indexURL(url)) {
Chris@439 44 cerr << "PluginRDFDescription: ERROR: Failed to query RDF description for plugin ID \""
Chris@439 45 << pluginId.toStdString() << "\"" << endl;
Chris@439 46 } else {
Chris@439 47 m_haveDescription = true;
Chris@439 48 }
Chris@439 49 }
Chris@439 50 }
Chris@439 51
Chris@439 52 PluginRDFDescription::~PluginRDFDescription()
Chris@439 53 {
Chris@468 54 //!!! delete m_source;
Chris@439 55 }
Chris@439 56
Chris@439 57 bool
Chris@439 58 PluginRDFDescription::haveDescription() const
Chris@439 59 {
Chris@439 60 return m_haveDescription;
Chris@439 61 }
Chris@439 62
Chris@457 63 QString
Chris@457 64 PluginRDFDescription::getPluginName() const
Chris@457 65 {
Chris@457 66 return m_pluginName;
Chris@457 67 }
Chris@457 68
Chris@457 69 QString
Chris@457 70 PluginRDFDescription::getPluginDescription() const
Chris@457 71 {
Chris@457 72 return m_pluginDescription;
Chris@457 73 }
Chris@457 74
Chris@457 75 QString
Chris@457 76 PluginRDFDescription::getPluginMaker() const
Chris@457 77 {
Chris@457 78 return m_pluginMaker;
Chris@457 79 }
Chris@457 80
Chris@462 81 QString
Chris@462 82 PluginRDFDescription::getPluginInfoURL() const
Chris@462 83 {
Chris@462 84 return m_pluginInfoURL;
Chris@462 85 }
Chris@462 86
Chris@457 87 QStringList
Chris@457 88 PluginRDFDescription::getOutputIds() const
Chris@457 89 {
Chris@457 90 QStringList ids;
Chris@457 91 for (OutputDispositionMap::const_iterator i = m_outputDispositions.begin();
Chris@457 92 i != m_outputDispositions.end(); ++i) {
Chris@457 93 ids.push_back(i->first);
Chris@457 94 }
Chris@457 95 return ids;
Chris@457 96 }
Chris@457 97
Chris@457 98 QString
Chris@457 99 PluginRDFDescription::getOutputName(QString outputId) const
Chris@457 100 {
Chris@457 101 if (m_outputNames.find(outputId) == m_outputNames.end()) {
Chris@457 102 return "";
Chris@457 103 }
Chris@457 104 return m_outputNames.find(outputId)->second;
Chris@457 105 }
Chris@457 106
Chris@439 107 PluginRDFDescription::OutputDisposition
Chris@439 108 PluginRDFDescription::getOutputDisposition(QString outputId) const
Chris@439 109 {
Chris@439 110 if (m_outputDispositions.find(outputId) == m_outputDispositions.end()) {
Chris@439 111 return OutputDispositionUnknown;
Chris@439 112 }
Chris@439 113 return m_outputDispositions.find(outputId)->second;
Chris@439 114 }
Chris@439 115
Chris@439 116 QString
Chris@439 117 PluginRDFDescription::getOutputEventTypeURI(QString outputId) const
Chris@439 118 {
Chris@439 119 if (m_outputEventTypeURIMap.find(outputId) ==
Chris@439 120 m_outputEventTypeURIMap.end()) {
Chris@439 121 return "";
Chris@439 122 }
Chris@439 123 return m_outputEventTypeURIMap.find(outputId)->second;
Chris@439 124 }
Chris@439 125
Chris@439 126 QString
Chris@440 127 PluginRDFDescription::getOutputFeatureAttributeURI(QString outputId) const
Chris@440 128 {
Chris@440 129 if (m_outputFeatureAttributeURIMap.find(outputId) ==
Chris@440 130 m_outputFeatureAttributeURIMap.end()) {
Chris@440 131 return "";
Chris@440 132 }
Chris@440 133 return m_outputFeatureAttributeURIMap.find(outputId)->second;
Chris@440 134 }
Chris@440 135
Chris@440 136 QString
Chris@440 137 PluginRDFDescription::getOutputSignalTypeURI(QString outputId) const
Chris@440 138 {
Chris@440 139 if (m_outputSignalTypeURIMap.find(outputId) ==
Chris@440 140 m_outputSignalTypeURIMap.end()) {
Chris@440 141 return "";
Chris@440 142 }
Chris@440 143 return m_outputSignalTypeURIMap.find(outputId)->second;
Chris@440 144 }
Chris@440 145
Chris@440 146 QString
Chris@439 147 PluginRDFDescription::getOutputUnit(QString outputId) const
Chris@439 148 {
Chris@439 149 if (m_outputUnitMap.find(outputId) == m_outputUnitMap.end()) {
Chris@439 150 return "";
Chris@439 151 }
Chris@439 152 return m_outputUnitMap.find(outputId)->second;
Chris@439 153 }
Chris@439 154
Chris@439 155 bool
Chris@439 156 PluginRDFDescription::indexURL(QString url)
Chris@439 157 {
Chris@457 158 Profiler profiler("PluginRDFDescription::indexURL");
Chris@457 159
Chris@439 160 QString type, soname, label;
Chris@439 161 PluginIdentifier::parseIdentifier(m_pluginId, type, soname, label);
Chris@439 162
Chris@457 163 bool success = true;
Chris@457 164
Chris@457 165 QString local = url;
Chris@457 166
Chris@457 167 if (FileSource::isRemote(url) &&
Chris@457 168 FileSource::canHandleScheme(url)) {
Chris@461 169
Chris@461 170 //!!! persistent with expiry
Chris@457 171
Chris@468 172 CachedFile cf(url);
Chris@468 173 if (!cf.isOK()) {
Chris@468 174 return false;
Chris@468 175 }
Chris@468 176
Chris@468 177 local = QUrl::fromLocalFile(cf.getLocalFilename()).toString();
Chris@468 178 /*!!!
Chris@461 179 m_source = new FileSource(url, 0, FileSource::PersistentCache);
Chris@461 180
Chris@457 181 if (!m_source->isAvailable()) {
Chris@457 182 delete m_source;
Chris@457 183 m_source = 0;
Chris@457 184 return false;
Chris@457 185 }
Chris@457 186 m_source->waitForData();
Chris@457 187 local = QUrl::fromLocalFile(m_source->getLocalFilename()).toString();
Chris@468 188 */
Chris@457 189 }
Chris@457 190
Chris@457 191 if (!indexMetadata(local, label)) success = false;
Chris@457 192 if (!indexOutputs(local, label)) success = false;
Chris@457 193
Chris@457 194 return success;
Chris@457 195 }
Chris@457 196
Chris@457 197 bool
Chris@457 198 PluginRDFDescription::indexMetadata(QString url, QString label)
Chris@457 199 {
Chris@457 200 Profiler profiler("PluginRDFDescription::indexMetadata");
Chris@457 201
Chris@457 202 QString queryTemplate =
Chris@457 203 QString(
Chris@457 204 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 205 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@457 206 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@457 207 " SELECT ?%4 FROM <%1> "
Chris@457 208 " WHERE { "
Chris@457 209 " ?plugin a vamp:Plugin ; "
Chris@457 210 " vamp:identifier \"%2\" ; "
Chris@457 211 " %3 ?%4 . "
Chris@457 212 " }")
Chris@457 213 .arg(url)
Chris@457 214 .arg(label);
Chris@457 215
Chris@457 216 SimpleSPARQLQuery::Value v;
Chris@457 217
Chris@457 218 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 219 (queryTemplate.arg("vamp:name").arg("name"), "name");
Chris@457 220
Chris@457 221 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 222 m_pluginName = v.value;
Chris@457 223 }
Chris@457 224
Chris@457 225 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 226 (queryTemplate.arg("dc:description").arg("description"), "description");
Chris@457 227
Chris@457 228 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 229 m_pluginDescription = v.value;
Chris@457 230 }
Chris@457 231
Chris@457 232 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 233 (QString(
Chris@457 234 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 235 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@457 236 " SELECT ?name FROM <%1> "
Chris@457 237 " WHERE { "
Chris@457 238 " ?plugin a vamp:Plugin ; "
Chris@457 239 " vamp:identifier \"%2\" ; "
Chris@457 240 " foaf:maker ?maker . "
Chris@457 241 " ?maker foaf:name ?name . "
Chris@457 242 " }")
Chris@457 243 .arg(url)
Chris@457 244 .arg(label), "name");
Chris@457 245
Chris@457 246 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 247 m_pluginMaker = v.value;
Chris@457 248 }
Chris@457 249
Chris@462 250 // If we have a more-information URL for this plugin, then we take
Chris@463 251 // that. Otherwise, a more-information URL for the plugin
Chris@462 252 // library would do nicely. Failing that, we could perhaps use
Chris@462 253 // any foaf:page URL at all that appears in the file -- but
Chris@462 254 // perhaps that would be unwise
Chris@462 255
Chris@462 256 v = SimpleSPARQLQuery::singleResultQuery
Chris@462 257 (QString(
Chris@462 258 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@462 259 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@462 260 " SELECT ?page from <%1> "
Chris@462 261 " WHERE { "
Chris@462 262 " ?plugin a vamp:Plugin ; "
Chris@462 263 " vamp:identifier \"%2\" ; "
Chris@462 264 " foaf:page ?page . "
Chris@462 265 " }")
Chris@462 266 .arg(url)
Chris@462 267 .arg(label), "page");
Chris@462 268
Chris@462 269 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@462 270
Chris@462 271 m_pluginInfoURL = v.value;
Chris@462 272
Chris@462 273 } else {
Chris@462 274
Chris@462 275 v = SimpleSPARQLQuery::singleResultQuery
Chris@462 276 (QString(
Chris@462 277 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@462 278 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@462 279 " SELECT ?page from <%1> "
Chris@462 280 " WHERE { "
Chris@462 281 " ?library a vamp:PluginLibrary ; "
Chris@462 282 " vamp:available_plugin ?plugin ; "
Chris@462 283 " foaf:page ?page . "
Chris@462 284 " ?plugin a vamp:Plugin ; "
Chris@462 285 " vamp:identifier \"%2\" . "
Chris@462 286 " }")
Chris@462 287 .arg(url)
Chris@462 288 .arg(label), "page");
Chris@462 289
Chris@462 290 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@462 291
Chris@462 292 m_pluginInfoURL = v.value;
Chris@462 293 }
Chris@462 294 }
Chris@462 295
Chris@457 296 return true;
Chris@457 297 }
Chris@457 298
Chris@457 299 bool
Chris@457 300 PluginRDFDescription::indexOutputs(QString url, QString label)
Chris@457 301 {
Chris@457 302 Profiler profiler("PluginRDFDescription::indexOutputs");
Chris@457 303
Chris@439 304 SimpleSPARQLQuery query
Chris@439 305 (QString
Chris@439 306 (
Chris@439 307 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@439 308
Chris@440 309 " SELECT ?output ?output_id ?output_type ?unit "
Chris@439 310 " FROM <%1> "
Chris@439 311
Chris@439 312 " WHERE { "
Chris@439 313
Chris@439 314 " ?plugin a vamp:Plugin ; "
Chris@439 315 " vamp:identifier \"%2\" ; "
Chris@440 316 " vamp:output ?output . "
Chris@439 317
Chris@439 318 " ?output vamp:identifier ?output_id ; "
Chris@439 319 " a ?output_type . "
Chris@439 320
Chris@439 321 " OPTIONAL { "
Chris@439 322 " ?output vamp:unit ?unit "
Chris@439 323 " } . "
Chris@439 324
Chris@439 325 " } "
Chris@439 326 )
Chris@439 327 .arg(url)
Chris@439 328 .arg(label));
Chris@439 329
Chris@439 330 SimpleSPARQLQuery::ResultList results = query.execute();
Chris@439 331
Chris@439 332 if (!query.isOK()) {
Chris@439 333 cerr << "ERROR: PluginRDFDescription::indexURL: ERROR: Failed to query document at <"
Chris@439 334 << url.toStdString() << ">: "
Chris@439 335 << query.getErrorString().toStdString() << endl;
Chris@439 336 return false;
Chris@439 337 }
Chris@439 338
Chris@439 339 if (results.empty()) {
Chris@439 340 cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: Document at <"
Chris@439 341 << url.toStdString()
Chris@440 342 << "> does not appear to describe any outputs for plugin with id \""
Chris@440 343 << label.toStdString() << "\"" << endl;
Chris@439 344 return false;
Chris@439 345 }
Chris@439 346
Chris@439 347 // Note that an output may appear more than once, if it inherits
Chris@439 348 // more than one type (e.g. DenseOutput and QuantizedOutput). So
Chris@439 349 // these results must accumulate
Chris@439 350
Chris@439 351 for (int i = 0; i < results.size(); ++i) {
Chris@439 352
Chris@440 353 QString outputUri = results[i]["output"].value;
Chris@439 354 QString outputId = results[i]["output_id"].value;
Chris@439 355 QString outputType = results[i]["output_type"].value;
Chris@439 356
Chris@439 357 if (outputType.contains("DenseOutput")) {
Chris@439 358 m_outputDispositions[outputId] = OutputDense;
Chris@439 359 } else if (outputType.contains("SparseOutput")) {
Chris@439 360 m_outputDispositions[outputId] = OutputSparse;
Chris@439 361 } else if (outputType.contains("TrackLevelOutput")) {
Chris@439 362 m_outputDispositions[outputId] = OutputTrackLevel;
Chris@457 363 } else {
Chris@457 364 m_outputDispositions[outputId] = OutputDispositionUnknown;
Chris@439 365 }
Chris@439 366
Chris@439 367 if (results[i]["unit"].type == SimpleSPARQLQuery::LiteralValue) {
Chris@439 368
Chris@439 369 QString unit = results[i]["unit"].value;
Chris@439 370
Chris@439 371 if (unit != "") {
Chris@439 372 m_outputUnitMap[outputId] = unit;
Chris@439 373 }
Chris@439 374 }
Chris@440 375
Chris@457 376 SimpleSPARQLQuery::Value v;
Chris@457 377
Chris@457 378 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 379 (QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 380 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@457 381 " SELECT ?title FROM <%1> "
Chris@457 382 " WHERE { <%2> dc:title ?title } ")
Chris@457 383 .arg(url).arg(outputUri), "title");
Chris@457 384
Chris@457 385 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 386 m_outputNames[outputId] = v.value;
Chris@457 387 }
Chris@457 388
Chris@440 389 QString queryTemplate =
Chris@440 390 QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@440 391 " SELECT ?%3 FROM <%1> "
Chris@440 392 " WHERE { <%2> vamp:computes_%3 ?%3 } ")
Chris@440 393 .arg(url).arg(outputUri);
Chris@440 394
Chris@440 395 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 396 (queryTemplate.arg("event_type"), "event_type");
Chris@440 397
Chris@440 398 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 399 m_outputEventTypeURIMap[outputId] = v.value;
Chris@440 400 }
Chris@440 401
Chris@440 402 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 403 (queryTemplate.arg("feature_attribute"), "feature_attribute");
Chris@440 404
Chris@440 405 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 406 m_outputFeatureAttributeURIMap[outputId] = v.value;
Chris@440 407 }
Chris@440 408
Chris@440 409 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 410 (queryTemplate.arg("signal_type"), "signal_type");
Chris@440 411
Chris@440 412 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 413 m_outputSignalTypeURIMap[outputId] = v.value;
Chris@440 414 }
Chris@439 415 }
Chris@439 416
Chris@439 417 return true;
Chris@439 418 }
Chris@439 419