annotate rdf/PluginRDFDescription.cpp @ 462:957e6a5c8495

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