annotate rdf/PluginRDFDescription.cpp @ 489:82ab61fa9223

* Reorganise our sparql queries on the basis that Redland must be available, not only optional. So for anything querying the pool of data about plugins, we use a single datastore and model which is initialised at the outset by PluginRDFIndexer and then queried directly; for anything that "reads from a file" (e.g. loading annotations) we query directly using Rasqal, going to the datastore when we need additional plugin-related information. This may improve performance, but mostly it simplifies the code and fixes a serious issue with RDF import in the previous versions (namely that multiple sequential RDF imports would end up sharing the same RDF data pool!)
author Chris Cannam
date Fri, 21 Nov 2008 16:12:29 +0000
parents a82645e788fc
children 81963c51b488
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@439 152 bool
Chris@489 153 PluginRDFDescription::index()
Chris@439 154 {
Chris@489 155 Profiler profiler("PluginRDFDescription::index");
Chris@439 156
Chris@457 157 bool success = true;
Chris@489 158 if (!indexMetadata()) success = false;
Chris@489 159 if (!indexOutputs()) success = false;
Chris@457 160
Chris@457 161 return success;
Chris@457 162 }
Chris@457 163
Chris@457 164 bool
Chris@489 165 PluginRDFDescription::indexMetadata()
Chris@457 166 {
Chris@489 167 Profiler profiler("PluginRDFDescription::index");
Chris@489 168
Chris@489 169 SimpleSPARQLQuery::QueryType m = SimpleSPARQLQuery::QueryFromModel;
Chris@457 170
Chris@457 171 QString queryTemplate =
Chris@457 172 QString(
Chris@457 173 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 174 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@457 175 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@489 176 " SELECT ?%3 "
Chris@457 177 " WHERE { "
Chris@489 178 " <%1> %2 ?%3 . "
Chris@457 179 " }")
Chris@489 180 .arg(m_pluginUri);
Chris@457 181
Chris@457 182 SimpleSPARQLQuery::Value v;
Chris@457 183
Chris@457 184 v = SimpleSPARQLQuery::singleResultQuery
Chris@489 185 (m, queryTemplate.arg("vamp:name").arg("name"), "name");
Chris@457 186
Chris@457 187 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 188 m_pluginName = v.value;
Chris@457 189 }
Chris@457 190
Chris@457 191 v = SimpleSPARQLQuery::singleResultQuery
Chris@489 192 (m, queryTemplate.arg("dc:description").arg("description"), "description");
Chris@457 193
Chris@457 194 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 195 m_pluginDescription = v.value;
Chris@457 196 }
Chris@457 197
Chris@457 198 v = SimpleSPARQLQuery::singleResultQuery
Chris@489 199 (m,
Chris@480 200 QString(
Chris@457 201 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 202 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@489 203 " SELECT ?name "
Chris@457 204 " WHERE { "
Chris@489 205 " <%1> foaf:maker ?maker . "
Chris@457 206 " ?maker foaf:name ?name . "
Chris@457 207 " }")
Chris@489 208 .arg(m_pluginUri),
Chris@489 209 "name");
Chris@457 210
Chris@457 211 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 212 m_pluginMaker = v.value;
Chris@457 213 }
Chris@457 214
Chris@462 215 // If we have a more-information URL for this plugin, then we take
Chris@463 216 // that. Otherwise, a more-information URL for the plugin
Chris@462 217 // library would do nicely. Failing that, we could perhaps use
Chris@462 218 // any foaf:page URL at all that appears in the file -- but
Chris@462 219 // perhaps that would be unwise
Chris@462 220
Chris@462 221 v = SimpleSPARQLQuery::singleResultQuery
Chris@489 222 (m,
Chris@480 223 QString(
Chris@462 224 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@462 225 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@489 226 " SELECT ?page "
Chris@462 227 " WHERE { "
Chris@489 228 " <%1> foaf:page ?page . "
Chris@462 229 " }")
Chris@489 230 .arg(m_pluginUri),
Chris@489 231 "page");
Chris@462 232
Chris@462 233 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@462 234
Chris@462 235 m_pluginInfoURL = v.value;
Chris@462 236
Chris@462 237 } else {
Chris@462 238
Chris@462 239 v = SimpleSPARQLQuery::singleResultQuery
Chris@489 240 (m,
Chris@480 241 QString(
Chris@462 242 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@462 243 " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
Chris@489 244 " SELECT ?page "
Chris@462 245 " WHERE { "
Chris@489 246 " ?library vamp:available_plugin <%1> ; "
Chris@489 247 " a vamp:PluginLibrary ; "
Chris@462 248 " foaf:page ?page . "
Chris@462 249 " }")
Chris@489 250 .arg(m_pluginUri),
Chris@489 251 "page");
Chris@462 252
Chris@462 253 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@462 254
Chris@462 255 m_pluginInfoURL = v.value;
Chris@462 256 }
Chris@462 257 }
Chris@462 258
Chris@457 259 return true;
Chris@457 260 }
Chris@457 261
Chris@457 262 bool
Chris@489 263 PluginRDFDescription::indexOutputs()
Chris@457 264 {
Chris@457 265 Profiler profiler("PluginRDFDescription::indexOutputs");
Chris@489 266
Chris@489 267 SimpleSPARQLQuery::QueryType m = SimpleSPARQLQuery::QueryFromModel;
Chris@457 268
Chris@439 269 SimpleSPARQLQuery query
Chris@489 270 (m,
Chris@480 271 QString
Chris@439 272 (
Chris@439 273 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@439 274
Chris@440 275 " SELECT ?output ?output_id ?output_type ?unit "
Chris@439 276
Chris@439 277 " WHERE { "
Chris@439 278
Chris@489 279 " <%1> vamp:output ?output . "
Chris@439 280
Chris@439 281 " ?output vamp:identifier ?output_id ; "
Chris@439 282 " a ?output_type . "
Chris@439 283
Chris@439 284 " OPTIONAL { "
Chris@439 285 " ?output vamp:unit ?unit "
Chris@439 286 " } . "
Chris@439 287
Chris@439 288 " } "
Chris@439 289 )
Chris@489 290 .arg(m_pluginUri));
Chris@439 291
Chris@439 292 SimpleSPARQLQuery::ResultList results = query.execute();
Chris@439 293
Chris@439 294 if (!query.isOK()) {
Chris@489 295 cerr << "ERROR: PluginRDFDescription::index: ERROR: Failed to query outputs for <"
Chris@489 296 << m_pluginUri.toStdString() << ">: "
Chris@439 297 << query.getErrorString().toStdString() << endl;
Chris@439 298 return false;
Chris@439 299 }
Chris@439 300
Chris@439 301 if (results.empty()) {
Chris@489 302 cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: No outputs defined for <"
Chris@489 303 << m_pluginUri.toStdString() << ">" << endl;
Chris@439 304 return false;
Chris@439 305 }
Chris@439 306
Chris@439 307 // Note that an output may appear more than once, if it inherits
Chris@439 308 // more than one type (e.g. DenseOutput and QuantizedOutput). So
Chris@439 309 // these results must accumulate
Chris@439 310
Chris@439 311 for (int i = 0; i < results.size(); ++i) {
Chris@439 312
Chris@440 313 QString outputUri = results[i]["output"].value;
Chris@439 314 QString outputId = results[i]["output_id"].value;
Chris@439 315 QString outputType = results[i]["output_type"].value;
Chris@439 316
Chris@439 317 if (outputType.contains("DenseOutput")) {
Chris@439 318 m_outputDispositions[outputId] = OutputDense;
Chris@439 319 } else if (outputType.contains("SparseOutput")) {
Chris@439 320 m_outputDispositions[outputId] = OutputSparse;
Chris@439 321 } else if (outputType.contains("TrackLevelOutput")) {
Chris@439 322 m_outputDispositions[outputId] = OutputTrackLevel;
Chris@457 323 } else {
Chris@457 324 m_outputDispositions[outputId] = OutputDispositionUnknown;
Chris@439 325 }
Chris@439 326
Chris@439 327 if (results[i]["unit"].type == SimpleSPARQLQuery::LiteralValue) {
Chris@439 328
Chris@439 329 QString unit = results[i]["unit"].value;
Chris@439 330
Chris@439 331 if (unit != "") {
Chris@439 332 m_outputUnitMap[outputId] = unit;
Chris@439 333 }
Chris@439 334 }
Chris@440 335
Chris@457 336 SimpleSPARQLQuery::Value v;
Chris@457 337
Chris@457 338 v = SimpleSPARQLQuery::singleResultQuery
Chris@489 339 (m,
Chris@480 340 QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@457 341 " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
Chris@489 342 " SELECT ?title "
Chris@457 343 " WHERE { <%2> dc:title ?title } ")
Chris@489 344 .arg(outputUri), "title");
Chris@457 345
Chris@457 346 if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
Chris@457 347 m_outputNames[outputId] = v.value;
Chris@457 348 }
Chris@457 349
Chris@440 350 QString queryTemplate =
Chris@440 351 QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
Chris@489 352 " SELECT ?%3 "
Chris@440 353 " WHERE { <%2> vamp:computes_%3 ?%3 } ")
Chris@489 354 .arg(outputUri);
Chris@440 355
Chris@440 356 v = SimpleSPARQLQuery::singleResultQuery
Chris@489 357 (m, queryTemplate.arg("event_type"), "event_type");
Chris@440 358
Chris@440 359 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 360 m_outputEventTypeURIMap[outputId] = v.value;
Chris@440 361 }
Chris@440 362
Chris@440 363 v = SimpleSPARQLQuery::singleResultQuery
Chris@489 364 (m, queryTemplate.arg("feature_attribute"), "feature_attribute");
Chris@440 365
Chris@440 366 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 367 m_outputFeatureAttributeURIMap[outputId] = v.value;
Chris@440 368 }
Chris@440 369
Chris@440 370 v = SimpleSPARQLQuery::singleResultQuery
Chris@489 371 (m, queryTemplate.arg("signal_type"), "signal_type");
Chris@440 372
Chris@440 373 if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
Chris@440 374 m_outputSignalTypeURIMap[outputId] = v.value;
Chris@440 375 }
Chris@439 376 }
Chris@439 377
Chris@439 378 return true;
Chris@439 379 }
Chris@439 380