annotate rdf/PluginRDFDescription.cpp @ 457:ef14acd6d102

* Add beginnings of capability to search plugins that are not yet installed -- lots more work to do here, though
author Chris Cannam
date Tue, 14 Oct 2008 16:36:35 +0000
parents 5746c559af15
children 2019d89ebcf9
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@457 80 QStringList
Chris@457 81 PluginRDFDescription::getOutputIds() const
Chris@457 82 {
Chris@457 83 QStringList ids;
Chris@457 84 for (OutputDispositionMap::const_iterator i = m_outputDispositions.begin();
Chris@457 85 i != m_outputDispositions.end(); ++i) {
Chris@457 86 ids.push_back(i->first);
Chris@457 87 }
Chris@457 88 return ids;
Chris@457 89 }
Chris@457 90
Chris@457 91 QString
Chris@457 92 PluginRDFDescription::getOutputName(QString outputId) const
Chris@457 93 {
Chris@457 94 if (m_outputNames.find(outputId) == m_outputNames.end()) {
Chris@457 95 return "";
Chris@457 96 }
Chris@457 97 return m_outputNames.find(outputId)->second;
Chris@457 98 }
Chris@457 99
Chris@439 100 PluginRDFDescription::OutputDisposition
Chris@439 101 PluginRDFDescription::getOutputDisposition(QString outputId) const
Chris@439 102 {
Chris@439 103 if (m_outputDispositions.find(outputId) == m_outputDispositions.end()) {
Chris@439 104 return OutputDispositionUnknown;
Chris@439 105 }
Chris@439 106 return m_outputDispositions.find(outputId)->second;
Chris@439 107 }
Chris@439 108
Chris@439 109 QString
Chris@439 110 PluginRDFDescription::getOutputEventTypeURI(QString outputId) const
Chris@439 111 {
Chris@439 112 if (m_outputEventTypeURIMap.find(outputId) ==
Chris@439 113 m_outputEventTypeURIMap.end()) {
Chris@439 114 return "";
Chris@439 115 }
Chris@439 116 return m_outputEventTypeURIMap.find(outputId)->second;
Chris@439 117 }
Chris@439 118
Chris@439 119 QString
Chris@440 120 PluginRDFDescription::getOutputFeatureAttributeURI(QString outputId) const
Chris@440 121 {
Chris@440 122 if (m_outputFeatureAttributeURIMap.find(outputId) ==
Chris@440 123 m_outputFeatureAttributeURIMap.end()) {
Chris@440 124 return "";
Chris@440 125 }
Chris@440 126 return m_outputFeatureAttributeURIMap.find(outputId)->second;
Chris@440 127 }
Chris@440 128
Chris@440 129 QString
Chris@440 130 PluginRDFDescription::getOutputSignalTypeURI(QString outputId) const
Chris@440 131 {
Chris@440 132 if (m_outputSignalTypeURIMap.find(outputId) ==
Chris@440 133 m_outputSignalTypeURIMap.end()) {
Chris@440 134 return "";
Chris@440 135 }
Chris@440 136 return m_outputSignalTypeURIMap.find(outputId)->second;
Chris@440 137 }
Chris@440 138
Chris@440 139 QString
Chris@439 140 PluginRDFDescription::getOutputUnit(QString outputId) const
Chris@439 141 {
Chris@439 142 if (m_outputUnitMap.find(outputId) == m_outputUnitMap.end()) {
Chris@439 143 return "";
Chris@439 144 }
Chris@439 145 return m_outputUnitMap.find(outputId)->second;
Chris@439 146 }
Chris@439 147
Chris@439 148 bool
Chris@439 149 PluginRDFDescription::indexURL(QString url)
Chris@439 150 {
Chris@457 151 Profiler profiler("PluginRDFDescription::indexURL");
Chris@457 152
Chris@439 153 QString type, soname, label;
Chris@439 154 PluginIdentifier::parseIdentifier(m_pluginId, type, soname, label);
Chris@439 155
Chris@457 156 bool success = true;
Chris@457 157
Chris@457 158 QString local = url;
Chris@457 159
Chris@457 160 if (FileSource::isRemote(url) &&
Chris@457 161 FileSource::canHandleScheme(url)) {
Chris@457 162
Chris@457 163 m_source = new FileSource(url);
Chris@457 164 if (!m_source->isAvailable()) {
Chris@457 165 delete m_source;
Chris@457 166 m_source = 0;
Chris@457 167 return false;
Chris@457 168 }
Chris@457 169 m_source->waitForData();
Chris@457 170 local = QUrl::fromLocalFile(m_source->getLocalFilename()).toString();
Chris@457 171 }
Chris@457 172
Chris@457 173 if (!indexMetadata(local, label)) success = false;
Chris@457 174 if (!indexOutputs(local, label)) success = false;
Chris@457 175
Chris@457 176 return success;
Chris@457 177 }
Chris@457 178
Chris@457 179 bool
Chris@457 180 PluginRDFDescription::indexMetadata(QString url, QString label)
Chris@457 181 {
Chris@457 182 Profiler profiler("PluginRDFDescription::indexMetadata");
Chris@457 183
Chris@457 184 QString queryTemplate =
Chris@457 185 QString(
Chris@457 186 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 187 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@457 188 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@457 189 " SELECT ?%4 FROM <%1> "
Chris@457 190 " WHERE { "
Chris@457 191 " ?plugin a vamp:Plugin ; "
Chris@457 192 " vamp:identifier \"%2\" ; "
Chris@457 193 " %3 ?%4 . "
Chris@457 194 " }")
Chris@457 195 .arg(url)
Chris@457 196 .arg(label);
Chris@457 197
Chris@457 198 SimpleSPARQLQuery::Value v;
Chris@457 199
Chris@457 200 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 201 (queryTemplate.arg("vamp:name").arg("name"), "name");
Chris@457 202
Chris@457 203 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 204 m_pluginName = v.value;
Chris@457 205 }
Chris@457 206
Chris@457 207 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 208 (queryTemplate.arg("dc:description").arg("description"), "description");
Chris@457 209
Chris@457 210 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 211 m_pluginDescription = v.value;
Chris@457 212 }
Chris@457 213
Chris@457 214 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 215 (QString(
Chris@457 216 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 217 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@457 218 " SELECT ?name FROM <%1> "
Chris@457 219 " WHERE { "
Chris@457 220 " ?plugin a vamp:Plugin ; "
Chris@457 221 " vamp:identifier \"%2\" ; "
Chris@457 222 " foaf:maker ?maker . "
Chris@457 223 " ?maker foaf:name ?name . "
Chris@457 224 " }")
Chris@457 225 .arg(url)
Chris@457 226 .arg(label), "name");
Chris@457 227
Chris@457 228 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 229 m_pluginMaker = v.value;
Chris@457 230 }
Chris@457 231
Chris@457 232 return true;
Chris@457 233 }
Chris@457 234
Chris@457 235 bool
Chris@457 236 PluginRDFDescription::indexOutputs(QString url, QString label)
Chris@457 237 {
Chris@457 238 Profiler profiler("PluginRDFDescription::indexOutputs");
Chris@457 239
Chris@439 240 SimpleSPARQLQuery query
Chris@439 241 (QString
Chris@439 242 (
Chris@439 243 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@439 244
Chris@440 245 " SELECT ?output ?output_id ?output_type ?unit "
Chris@439 246 " FROM <%1> "
Chris@439 247
Chris@439 248 " WHERE { "
Chris@439 249
Chris@439 250 " ?plugin a vamp:Plugin ; "
Chris@439 251 " vamp:identifier \"%2\" ; "
Chris@440 252 " vamp:output ?output . "
Chris@439 253
Chris@439 254 " ?output vamp:identifier ?output_id ; "
Chris@439 255 " a ?output_type . "
Chris@439 256
Chris@439 257 " OPTIONAL { "
Chris@439 258 " ?output vamp:unit ?unit "
Chris@439 259 " } . "
Chris@439 260
Chris@439 261 " } "
Chris@439 262 )
Chris@439 263 .arg(url)
Chris@439 264 .arg(label));
Chris@439 265
Chris@439 266 SimpleSPARQLQuery::ResultList results = query.execute();
Chris@439 267
Chris@439 268 if (!query.isOK()) {
Chris@439 269 cerr << "ERROR: PluginRDFDescription::indexURL: ERROR: Failed to query document at <"
Chris@439 270 << url.toStdString() << ">: "
Chris@439 271 << query.getErrorString().toStdString() << endl;
Chris@439 272 return false;
Chris@439 273 }
Chris@439 274
Chris@439 275 if (results.empty()) {
Chris@439 276 cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: Document at <"
Chris@439 277 << url.toStdString()
Chris@440 278 << "> does not appear to describe any outputs for plugin with id \""
Chris@440 279 << label.toStdString() << "\"" << endl;
Chris@439 280 return false;
Chris@439 281 }
Chris@439 282
Chris@439 283 // Note that an output may appear more than once, if it inherits
Chris@439 284 // more than one type (e.g. DenseOutput and QuantizedOutput). So
Chris@439 285 // these results must accumulate
Chris@439 286
Chris@439 287 for (int i = 0; i < results.size(); ++i) {
Chris@439 288
Chris@440 289 QString outputUri = results[i]["output"].value;
Chris@439 290 QString outputId = results[i]["output_id"].value;
Chris@439 291 QString outputType = results[i]["output_type"].value;
Chris@439 292
Chris@439 293 if (outputType.contains("DenseOutput")) {
Chris@439 294 m_outputDispositions[outputId] = OutputDense;
Chris@439 295 } else if (outputType.contains("SparseOutput")) {
Chris@439 296 m_outputDispositions[outputId] = OutputSparse;
Chris@439 297 } else if (outputType.contains("TrackLevelOutput")) {
Chris@439 298 m_outputDispositions[outputId] = OutputTrackLevel;
Chris@457 299 } else {
Chris@457 300 m_outputDispositions[outputId] = OutputDispositionUnknown;
Chris@439 301 }
Chris@439 302
Chris@439 303 if (results[i]["unit"].type == SimpleSPARQLQuery::LiteralValue) {
Chris@439 304
Chris@439 305 QString unit = results[i]["unit"].value;
Chris@439 306
Chris@439 307 if (unit != "") {
Chris@439 308 m_outputUnitMap[outputId] = unit;
Chris@439 309 }
Chris@439 310 }
Chris@440 311
Chris@457 312 SimpleSPARQLQuery::Value v;
Chris@457 313
Chris@457 314 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 315 (QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 316 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@457 317 " SELECT ?title FROM <%1> "
Chris@457 318 " WHERE { <%2> dc:title ?title } ")
Chris@457 319 .arg(url).arg(outputUri), "title");
Chris@457 320
Chris@457 321 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 322 m_outputNames[outputId] = v.value;
Chris@457 323 }
Chris@457 324
Chris@440 325 QString queryTemplate =
Chris@440 326 QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@440 327 " SELECT ?%3 FROM <%1> "
Chris@440 328 " WHERE { <%2> vamp:computes_%3 ?%3 } ")
Chris@440 329 .arg(url).arg(outputUri);
Chris@440 330
Chris@440 331 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 332 (queryTemplate.arg("event_type"), "event_type");
Chris@440 333
Chris@440 334 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 335 m_outputEventTypeURIMap[outputId] = v.value;
Chris@440 336 }
Chris@440 337
Chris@440 338 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 339 (queryTemplate.arg("feature_attribute"), "feature_attribute");
Chris@440 340
Chris@440 341 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 342 m_outputFeatureAttributeURIMap[outputId] = v.value;
Chris@440 343 }
Chris@440 344
Chris@440 345 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 346 (queryTemplate.arg("signal_type"), "signal_type");
Chris@440 347
Chris@440 348 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 349 m_outputSignalTypeURIMap[outputId] = v.value;
Chris@440 350 }
Chris@439 351 }
Chris@439 352
Chris@439 353 return true;
Chris@439 354 }
Chris@439 355