Mercurial > hg > svcore
view rdf/RDFTransformFactory.cpp @ 449:a75edaa08d28
* Support importing features from RDF whose times are intervals rather
than only instants; import them into region or note models. Sadly
this makes RDF import much, much slower, because we need to work around
Rasqal's single-OPTIONAL limitation by repeatedly querying each feature
for time and range.
* Add segmentation view to region layer, and display label texts
author | Chris Cannam |
---|---|
date | Tue, 07 Oct 2008 12:42:17 +0000 |
parents | 5746c559af15 |
children | 3ffce691c9bf |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Sonic Visualiser An audio file viewer and annotation editor. Centre for Digital Music, Queen Mary, University of London. This file copyright 2008 QMUL. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include "RDFTransformFactory.h" #include <map> #include <vector> #include <iostream> #include <cmath> #include "SimpleSPARQLQuery.h" #include "PluginRDFIndexer.h" #include "base/ProgressReporter.h" #include "transform/TransformFactory.h" using std::cerr; using std::endl; typedef const unsigned char *STR; // redland's expected string type class RDFTransformFactoryImpl { public: RDFTransformFactoryImpl(QString url); virtual ~RDFTransformFactoryImpl(); bool isOK(); QString getErrorString() const; std::vector<Transform> getTransforms(ProgressReporter *); protected: QString m_urlString; QString m_errorString; bool setOutput(Transform &, QString, QString); bool setParameters(Transform &, QString, QString); }; QString RDFTransformFactory::getKnownExtensions() { return "*.rdf *.n3 *.ttl"; } RDFTransformFactory::RDFTransformFactory(QString url) : m_d(new RDFTransformFactoryImpl(url)) { } RDFTransformFactory::~RDFTransformFactory() { delete m_d; } bool RDFTransformFactory::isOK() { return m_d->isOK(); } QString RDFTransformFactory::getErrorString() const { return m_d->getErrorString(); } std::vector<Transform> RDFTransformFactory::getTransforms(ProgressReporter *r) { return m_d->getTransforms(r); } RDFTransformFactoryImpl::RDFTransformFactoryImpl(QString url) : m_urlString(url) { } RDFTransformFactoryImpl::~RDFTransformFactoryImpl() { } bool RDFTransformFactoryImpl::isOK() { return (m_errorString == ""); } QString RDFTransformFactoryImpl::getErrorString() const { return m_errorString; } std::vector<Transform> RDFTransformFactoryImpl::getTransforms(ProgressReporter *reporter) { std::vector<Transform> transforms; // We have to do this a very long way round, to work around // rasqal's current inability to handle correctly more than one // OPTIONAL graph in a query const char *optionals[] = { "output", "program", "step_size", "block_size", "window_type", "sample_rate", "start", "duration" }; std::map<QString, Transform> uriTransformMap; QString queryTemplate = " PREFIX vamp: <http://purl.org/ontology/vamp/> " " SELECT ?transform ?plugin %1 " " FROM <%2> " " WHERE { " " ?transform a vamp:Transform ; " " vamp:plugin ?plugin . " " %3 " " } "; SimpleSPARQLQuery transformsQuery (queryTemplate.arg("").arg(m_urlString).arg("")); SimpleSPARQLQuery::ResultList transformResults = transformsQuery.execute(); if (!transformsQuery.isOK()) { m_errorString = transformsQuery.getErrorString(); return transforms; } if (transformResults.empty()) { cerr << "RDFTransformFactory: NOTE: No RDF/TTL transform descriptions found in document at <" << m_urlString.toStdString() << ">" << endl; return transforms; } PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance(); for (int i = 0; i < transformResults.size(); ++i) { SimpleSPARQLQuery::KeyValueMap &result = transformResults[i]; QString transformUri = result["transform"].value; QString pluginUri = result["plugin"].value; QString pluginId = indexer->getIdForPluginURI(pluginUri); if (pluginId == "") { cerr << "RDFTransformFactory: WARNING: Unknown plugin <" << pluginUri.toStdString() << "> for transform <" << transformUri.toStdString() << ">, skipping this transform" << endl; continue; } QString pluginDescriptionURL = indexer->getDescriptionURLForPluginId(pluginId); if (pluginDescriptionURL == "") { cerr << "RDFTransformFactory: WARNING: No RDF description available for plugin <" << pluginUri.toStdString() << ">, skipping transform <" << transformUri.toStdString() << ">" << endl; continue; } Transform transform; transform.setPluginIdentifier(pluginId); if (!setOutput(transform, transformUri, pluginDescriptionURL)) { return transforms; } if (!setParameters(transform, transformUri, pluginDescriptionURL)) { return transforms; } uriTransformMap[transformUri] = transform; } for (int i = 0; i < sizeof(optionals)/sizeof(optionals[0]); ++i) { QString optional = optionals[i]; SimpleSPARQLQuery query (queryTemplate .arg(QString("?%1").arg(optional)) .arg(m_urlString) .arg(QString("?transform vamp:%1 ?%2") .arg(optionals[i]).arg(optional))); SimpleSPARQLQuery::ResultList results = query.execute(); if (!query.isOK()) { m_errorString = query.getErrorString(); return transforms; } if (results.empty()) continue; for (int j = 0; j < results.size(); ++j) { QString transformUri = results[j]["transform"].value; if (uriTransformMap.find(transformUri) == uriTransformMap.end()) { cerr << "RDFTransformFactory: ERROR: Transform URI <" << transformUri.toStdString() << "> not found in internal map!" << endl; continue; } Transform &transform = uriTransformMap[transformUri]; const SimpleSPARQLQuery::Value &v = results[j][optional]; if (v.type == SimpleSPARQLQuery::LiteralValue) { if (optional == "program") { transform.setProgram(v.value); } else if (optional == "step_size") { transform.setStepSize(v.value.toUInt()); } else if (optional == "block_size") { transform.setBlockSize(v.value.toUInt()); } else if (optional == "window_type") { cerr << "NOTE: can't handle window type yet (value is \"" << v.value.toStdString() << "\")" << endl; } else if (optional == "sample_rate") { transform.setSampleRate(v.value.toFloat()); } else if (optional == "start") { transform.setStartTime (RealTime::fromXsdDuration(v.value.toStdString())); } else if (optional == "duration") { transform.setDuration (RealTime::fromXsdDuration(v.value.toStdString())); } else { cerr << "RDFTransformFactory: ERROR: Inconsistent optionals lists (unexpected optional \"" << optional.toStdString() << "\"" << endl; } } } } for (std::map<QString, Transform>::iterator i = uriTransformMap.begin(); i != uriTransformMap.end(); ++i) { Transform &transform = i->second; cerr << "RDFTransformFactory: NOTE: Transform is: " << endl; cerr << transform.toXmlString().toStdString() << endl; transforms.push_back(transform); } return transforms; } bool RDFTransformFactoryImpl::setOutput(Transform &transform, QString transformUri, QString pluginDescriptionURL) { SimpleSPARQLQuery outputQuery (QString ( " PREFIX vamp: <http://purl.org/ontology/vamp/> " " SELECT ?output_id " " FROM <%1> " " FROM <%2> " " WHERE { " " <%3> vamp:output ?output . " " ?output vamp:identifier ?output_id " " } " ) .arg(m_urlString) .arg(pluginDescriptionURL) .arg(transformUri)); SimpleSPARQLQuery::ResultList outputResults = outputQuery.execute(); if (!outputQuery.isOK()) { m_errorString = outputQuery.getErrorString(); return false; } if (outputQuery.wasCancelled()) { m_errorString = "Query cancelled"; return false; } for (int j = 0; j < outputResults.size(); ++j) { QString outputId = outputResults[j]["output_id"].value; transform.setOutput(outputId); } return true; } bool RDFTransformFactoryImpl::setParameters(Transform &transform, QString transformUri, QString pluginDescriptionURL) { SimpleSPARQLQuery paramQuery (QString ( " PREFIX vamp: <http://purl.org/ontology/vamp/> " " SELECT ?param_id ?param_value " " FROM <%1> " " FROM <%2> " " WHERE { " " <%3> vamp:parameter_binding ?binding . " " ?binding vamp:parameter ?param ; " " vamp:value ?param_value . " " ?param vamp:identifier ?param_id " " } " ) .arg(m_urlString) .arg(pluginDescriptionURL) .arg(transformUri)); SimpleSPARQLQuery::ResultList paramResults = paramQuery.execute(); if (!paramQuery.isOK()) { m_errorString = paramQuery.getErrorString(); return false; } if (paramQuery.wasCancelled()) { m_errorString = "Query cancelled"; return false; } for (int j = 0; j < paramResults.size(); ++j) { QString paramId = paramResults[j]["param_id"].value; QString paramValue = paramResults[j]["param_value"].value; if (paramId == "" || paramValue == "") continue; transform.setParameter(paramId, paramValue.toFloat()); } return true; }