annotate rdf/PluginRDFDescription.cpp @ 473:47b41ec34407

* Avoid waiting on uninstalled transforms mutex in TransformFactory:: getTransformInstallStatus -- we can return TransformUnknown * Don't follow link in SelectableLabel when clicking to select it * Restore lost version number in plugin param dialog
author Chris Cannam
date Tue, 28 Oct 2008 18:06:06 +0000
parents 0dc158c1a6c9
children 3ffce691c9bf
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@457 194 " ?plugin a vamp:Plugin ; "
Chris@457 195 " vamp:identifier \"%2\" ; "
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@457 204 (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@457 211 (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@457 218 (QString(
Chris@457 219 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 220 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@457 221 " SELECT ?name FROM <%1> "
Chris@457 222 " WHERE { "
Chris@457 223 " ?plugin a vamp:Plugin ; "
Chris@457 224 " vamp:identifier \"%2\" ; "
Chris@457 225 " foaf:maker ?maker . "
Chris@457 226 " ?maker foaf:name ?name . "
Chris@457 227 " }")
Chris@457 228 .arg(url)
Chris@457 229 .arg(label), "name");
Chris@457 230
Chris@457 231 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 232 m_pluginMaker = v.value;
Chris@457 233 }
Chris@457 234
Chris@462 235 // If we have a more-information URL for this plugin, then we take
Chris@463 236 // that. Otherwise, a more-information URL for the plugin
Chris@462 237 // library would do nicely. Failing that, we could perhaps use
Chris@462 238 // any foaf:page URL at all that appears in the file -- but
Chris@462 239 // perhaps that would be unwise
Chris@462 240
Chris@462 241 v = SimpleSPARQLQuery::singleResultQuery
Chris@462 242 (QString(
Chris@462 243 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@462 244 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@462 245 " SELECT ?page from <%1> "
Chris@462 246 " WHERE { "
Chris@462 247 " ?plugin a vamp:Plugin ; "
Chris@462 248 " vamp:identifier \"%2\" ; "
Chris@462 249 " foaf:page ?page . "
Chris@462 250 " }")
Chris@462 251 .arg(url)
Chris@462 252 .arg(label), "page");
Chris@462 253
Chris@462 254 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@462 255
Chris@462 256 m_pluginInfoURL = v.value;
Chris@462 257
Chris@462 258 } else {
Chris@462 259
Chris@462 260 v = SimpleSPARQLQuery::singleResultQuery
Chris@462 261 (QString(
Chris@462 262 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@462 263 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@462 264 " SELECT ?page from <%1> "
Chris@462 265 " WHERE { "
Chris@462 266 " ?library a vamp:PluginLibrary ; "
Chris@462 267 " vamp:available_plugin ?plugin ; "
Chris@462 268 " foaf:page ?page . "
Chris@462 269 " ?plugin a vamp:Plugin ; "
Chris@462 270 " vamp:identifier \"%2\" . "
Chris@462 271 " }")
Chris@462 272 .arg(url)
Chris@462 273 .arg(label), "page");
Chris@462 274
Chris@462 275 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@462 276
Chris@462 277 m_pluginInfoURL = v.value;
Chris@462 278 }
Chris@462 279 }
Chris@462 280
Chris@457 281 return true;
Chris@457 282 }
Chris@457 283
Chris@457 284 bool
Chris@457 285 PluginRDFDescription::indexOutputs(QString url, QString label)
Chris@457 286 {
Chris@457 287 Profiler profiler("PluginRDFDescription::indexOutputs");
Chris@457 288
Chris@439 289 SimpleSPARQLQuery query
Chris@439 290 (QString
Chris@439 291 (
Chris@439 292 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@439 293
Chris@440 294 " SELECT ?output ?output_id ?output_type ?unit "
Chris@439 295 " FROM <%1> "
Chris@439 296
Chris@439 297 " WHERE { "
Chris@439 298
Chris@439 299 " ?plugin a vamp:Plugin ; "
Chris@439 300 " vamp:identifier \"%2\" ; "
Chris@440 301 " vamp:output ?output . "
Chris@439 302
Chris@439 303 " ?output vamp:identifier ?output_id ; "
Chris@439 304 " a ?output_type . "
Chris@439 305
Chris@439 306 " OPTIONAL { "
Chris@439 307 " ?output vamp:unit ?unit "
Chris@439 308 " } . "
Chris@439 309
Chris@439 310 " } "
Chris@439 311 )
Chris@439 312 .arg(url)
Chris@439 313 .arg(label));
Chris@439 314
Chris@439 315 SimpleSPARQLQuery::ResultList results = query.execute();
Chris@439 316
Chris@439 317 if (!query.isOK()) {
Chris@439 318 cerr << "ERROR: PluginRDFDescription::indexURL: ERROR: Failed to query document at <"
Chris@439 319 << url.toStdString() << ">: "
Chris@439 320 << query.getErrorString().toStdString() << endl;
Chris@439 321 return false;
Chris@439 322 }
Chris@439 323
Chris@439 324 if (results.empty()) {
Chris@439 325 cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: Document at <"
Chris@439 326 << url.toStdString()
Chris@440 327 << "> does not appear to describe any outputs for plugin with id \""
Chris@440 328 << label.toStdString() << "\"" << endl;
Chris@439 329 return false;
Chris@439 330 }
Chris@439 331
Chris@439 332 // Note that an output may appear more than once, if it inherits
Chris@439 333 // more than one type (e.g. DenseOutput and QuantizedOutput). So
Chris@439 334 // these results must accumulate
Chris@439 335
Chris@439 336 for (int i = 0; i < results.size(); ++i) {
Chris@439 337
Chris@440 338 QString outputUri = results[i]["output"].value;
Chris@439 339 QString outputId = results[i]["output_id"].value;
Chris@439 340 QString outputType = results[i]["output_type"].value;
Chris@439 341
Chris@439 342 if (outputType.contains("DenseOutput")) {
Chris@439 343 m_outputDispositions[outputId] = OutputDense;
Chris@439 344 } else if (outputType.contains("SparseOutput")) {
Chris@439 345 m_outputDispositions[outputId] = OutputSparse;
Chris@439 346 } else if (outputType.contains("TrackLevelOutput")) {
Chris@439 347 m_outputDispositions[outputId] = OutputTrackLevel;
Chris@457 348 } else {
Chris@457 349 m_outputDispositions[outputId] = OutputDispositionUnknown;
Chris@439 350 }
Chris@439 351
Chris@439 352 if (results[i]["unit"].type == SimpleSPARQLQuery::LiteralValue) {
Chris@439 353
Chris@439 354 QString unit = results[i]["unit"].value;
Chris@439 355
Chris@439 356 if (unit != "") {
Chris@439 357 m_outputUnitMap[outputId] = unit;
Chris@439 358 }
Chris@439 359 }
Chris@440 360
Chris@457 361 SimpleSPARQLQuery::Value v;
Chris@457 362
Chris@457 363 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 364 (QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 365 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@457 366 " SELECT ?title FROM <%1> "
Chris@457 367 " WHERE { <%2> dc:title ?title } ")
Chris@457 368 .arg(url).arg(outputUri), "title");
Chris@457 369
Chris@457 370 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 371 m_outputNames[outputId] = v.value;
Chris@457 372 }
Chris@457 373
Chris@440 374 QString queryTemplate =
Chris@440 375 QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@440 376 " SELECT ?%3 FROM <%1> "
Chris@440 377 " WHERE { <%2> vamp:computes_%3 ?%3 } ")
Chris@440 378 .arg(url).arg(outputUri);
Chris@440 379
Chris@440 380 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 381 (queryTemplate.arg("event_type"), "event_type");
Chris@440 382
Chris@440 383 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 384 m_outputEventTypeURIMap[outputId] = v.value;
Chris@440 385 }
Chris@440 386
Chris@440 387 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 388 (queryTemplate.arg("feature_attribute"), "feature_attribute");
Chris@440 389
Chris@440 390 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 391 m_outputFeatureAttributeURIMap[outputId] = v.value;
Chris@440 392 }
Chris@440 393
Chris@440 394 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 395 (queryTemplate.arg("signal_type"), "signal_type");
Chris@440 396
Chris@440 397 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 398 m_outputSignalTypeURIMap[outputId] = v.value;
Chris@440 399 }
Chris@439 400 }
Chris@439 401
Chris@439 402 return true;
Chris@439 403 }
Chris@439 404