annotate rdf/PluginRDFDescription.cpp @ 461:2019d89ebcf9

* Some work on querying and cacheing plugin RDF from a central index
author Chris Cannam
date Fri, 17 Oct 2008 15:26:29 +0000
parents ef14acd6d102
children 957e6a5c8495
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@461 162
Chris@461 163 //!!! persistent with expiry
Chris@457 164
Chris@461 165 m_source = new FileSource(url, 0, FileSource::PersistentCache);
Chris@461 166
Chris@457 167 if (!m_source->isAvailable()) {
Chris@457 168 delete m_source;
Chris@457 169 m_source = 0;
Chris@457 170 return false;
Chris@457 171 }
Chris@457 172 m_source->waitForData();
Chris@457 173 local = QUrl::fromLocalFile(m_source->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@457 235 return true;
Chris@457 236 }
Chris@457 237
Chris@457 238 bool
Chris@457 239 PluginRDFDescription::indexOutputs(QString url, QString label)
Chris@457 240 {
Chris@457 241 Profiler profiler("PluginRDFDescription::indexOutputs");
Chris@457 242
Chris@439 243 SimpleSPARQLQuery query
Chris@439 244 (QString
Chris@439 245 (
Chris@439 246 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@439 247
Chris@440 248 " SELECT ?output ?output_id ?output_type ?unit "
Chris@439 249 " FROM <%1> "
Chris@439 250
Chris@439 251 " WHERE { "
Chris@439 252
Chris@439 253 " ?plugin a vamp:Plugin ; "
Chris@439 254 " vamp:identifier \"%2\" ; "
Chris@440 255 " vamp:output ?output . "
Chris@439 256
Chris@439 257 " ?output vamp:identifier ?output_id ; "
Chris@439 258 " a ?output_type . "
Chris@439 259
Chris@439 260 " OPTIONAL { "
Chris@439 261 " ?output vamp:unit ?unit "
Chris@439 262 " } . "
Chris@439 263
Chris@439 264 " } "
Chris@439 265 )
Chris@439 266 .arg(url)
Chris@439 267 .arg(label));
Chris@439 268
Chris@439 269 SimpleSPARQLQuery::ResultList results = query.execute();
Chris@439 270
Chris@439 271 if (!query.isOK()) {
Chris@439 272 cerr << "ERROR: PluginRDFDescription::indexURL: ERROR: Failed to query document at <"
Chris@439 273 << url.toStdString() << ">: "
Chris@439 274 << query.getErrorString().toStdString() << endl;
Chris@439 275 return false;
Chris@439 276 }
Chris@439 277
Chris@439 278 if (results.empty()) {
Chris@439 279 cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: Document at <"
Chris@439 280 << url.toStdString()
Chris@440 281 << "> does not appear to describe any outputs for plugin with id \""
Chris@440 282 << label.toStdString() << "\"" << endl;
Chris@439 283 return false;
Chris@439 284 }
Chris@439 285
Chris@439 286 // Note that an output may appear more than once, if it inherits
Chris@439 287 // more than one type (e.g. DenseOutput and QuantizedOutput). So
Chris@439 288 // these results must accumulate
Chris@439 289
Chris@439 290 for (int i = 0; i < results.size(); ++i) {
Chris@439 291
Chris@440 292 QString outputUri = results[i]["output"].value;
Chris@439 293 QString outputId = results[i]["output_id"].value;
Chris@439 294 QString outputType = results[i]["output_type"].value;
Chris@439 295
Chris@439 296 if (outputType.contains("DenseOutput")) {
Chris@439 297 m_outputDispositions[outputId] = OutputDense;
Chris@439 298 } else if (outputType.contains("SparseOutput")) {
Chris@439 299 m_outputDispositions[outputId] = OutputSparse;
Chris@439 300 } else if (outputType.contains("TrackLevelOutput")) {
Chris@439 301 m_outputDispositions[outputId] = OutputTrackLevel;
Chris@457 302 } else {
Chris@457 303 m_outputDispositions[outputId] = OutputDispositionUnknown;
Chris@439 304 }
Chris@439 305
Chris@439 306 if (results[i]["unit"].type == SimpleSPARQLQuery::LiteralValue) {
Chris@439 307
Chris@439 308 QString unit = results[i]["unit"].value;
Chris@439 309
Chris@439 310 if (unit != "") {
Chris@439 311 m_outputUnitMap[outputId] = unit;
Chris@439 312 }
Chris@439 313 }
Chris@440 314
Chris@457 315 SimpleSPARQLQuery::Value v;
Chris@457 316
Chris@457 317 v = SimpleSPARQLQuery::singleResultQuery
Chris@457 318 (QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 319 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@457 320 " SELECT ?title FROM <%1> "
Chris@457 321 " WHERE { <%2> dc:title ?title } ")
Chris@457 322 .arg(url).arg(outputUri), "title");
Chris@457 323
Chris@457 324 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 325 m_outputNames[outputId] = v.value;
Chris@457 326 }
Chris@457 327
Chris@440 328 QString queryTemplate =
Chris@440 329 QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@440 330 " SELECT ?%3 FROM <%1> "
Chris@440 331 " WHERE { <%2> vamp:computes_%3 ?%3 } ")
Chris@440 332 .arg(url).arg(outputUri);
Chris@440 333
Chris@440 334 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 335 (queryTemplate.arg("event_type"), "event_type");
Chris@440 336
Chris@440 337 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 338 m_outputEventTypeURIMap[outputId] = v.value;
Chris@440 339 }
Chris@440 340
Chris@440 341 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 342 (queryTemplate.arg("feature_attribute"), "feature_attribute");
Chris@440 343
Chris@440 344 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 345 m_outputFeatureAttributeURIMap[outputId] = v.value;
Chris@440 346 }
Chris@440 347
Chris@440 348 v = SimpleSPARQLQuery::singleResultQuery
Chris@440 349 (queryTemplate.arg("signal_type"), "signal_type");
Chris@440 350
Chris@440 351 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 352 m_outputSignalTypeURIMap[outputId] = v.value;
Chris@440 353 }
Chris@439 354 }
Chris@439 355
Chris@439 356 return true;
Chris@439 357 }
Chris@439 358