annotate rdf/PluginRDFDescription.cpp @ 507:0944d13689b2

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