Chris@439: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@439: Chris@439: /* Chris@439: Sonic Visualiser Chris@439: An audio file viewer and annotation editor. Chris@439: Centre for Digital Music, Queen Mary, University of London. Chris@439: This file copyright 2008 QMUL. Chris@439: Chris@439: This program is free software; you can redistribute it and/or Chris@439: modify it under the terms of the GNU General Public License as Chris@439: published by the Free Software Foundation; either version 2 of the Chris@439: License, or (at your option) any later version. See the file Chris@439: COPYING included with this distribution for more information. Chris@439: */ Chris@439: Chris@439: #include "SimpleSPARQLQuery.h" Chris@439: #include "base/ProgressReporter.h" Chris@439: Chris@440: #ifdef USE_NEW_RASQAL_API Chris@440: #include Chris@440: #else Chris@439: #include Chris@440: #endif Chris@439: Chris@439: #include Chris@439: Chris@439: using std::cerr; Chris@439: using std::endl; Chris@439: Chris@440: #ifdef USE_NEW_RASQAL_API Chris@440: class WrasqalWorldWrapper // wrong but wromantic, etc Chris@440: { Chris@440: public: Chris@440: WrasqalWorldWrapper() : m_world(rasqal_new_world()) { } Chris@440: ~WrasqalWorldWrapper() { rasqal_free_world(m_world); } Chris@440: Chris@440: rasqal_world *getWorld() const { return m_world; } Chris@440: Chris@440: private: Chris@440: rasqal_world *m_world; Chris@440: }; Chris@440: #endif Chris@440: Chris@439: class SimpleSPARQLQuery::Impl Chris@439: { Chris@439: public: Chris@439: Impl(QString query); Chris@439: ~Impl(); Chris@439: Chris@439: void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; } Chris@439: bool wasCancelled() const { return m_cancelled; } Chris@439: Chris@439: ResultList execute(); Chris@439: Chris@439: bool isOK() const; Chris@439: QString getErrorString() const; Chris@439: Chris@439: protected: Chris@439: static void errorHandler(void *, raptor_locator *, const char *); Chris@439: Chris@440: #ifdef USE_NEW_RASQAL_API Chris@440: static WrasqalWorldWrapper m_www; Chris@440: #else Chris@439: static bool m_initialised; Chris@440: #endif Chris@439: Chris@439: QString m_query; Chris@439: QString m_errorString; Chris@439: ProgressReporter *m_reporter; Chris@439: bool m_cancelled; Chris@439: }; Chris@439: Chris@440: #ifdef USE_NEW_RASQAL_API Chris@440: WrasqalWorldWrapper Chris@440: SimpleSPARQLQuery::Impl::m_www; Chris@440: #else Chris@440: bool Chris@440: SimpleSPARQLQuery::Impl::m_initialised = false; Chris@440: #endif Chris@440: Chris@439: SimpleSPARQLQuery::SimpleSPARQLQuery(QString query) : Chris@439: m_impl(new Impl(query)) { } Chris@439: Chris@439: SimpleSPARQLQuery::~SimpleSPARQLQuery() Chris@439: { Chris@439: delete m_impl; Chris@439: } Chris@439: Chris@439: void Chris@439: SimpleSPARQLQuery::setProgressReporter(ProgressReporter *reporter) Chris@439: { Chris@439: m_impl->setProgressReporter(reporter); Chris@439: } Chris@439: Chris@439: bool Chris@439: SimpleSPARQLQuery::wasCancelled() const Chris@439: { Chris@439: return m_impl->wasCancelled(); Chris@439: } Chris@439: Chris@439: SimpleSPARQLQuery::ResultList Chris@439: SimpleSPARQLQuery::execute() Chris@439: { Chris@439: return m_impl->execute(); Chris@439: } Chris@439: Chris@439: bool Chris@439: SimpleSPARQLQuery::isOK() const Chris@439: { Chris@439: return m_impl->isOK(); Chris@439: } Chris@439: Chris@439: QString Chris@439: SimpleSPARQLQuery::getErrorString() const Chris@439: { Chris@439: return m_impl->getErrorString(); Chris@439: } Chris@439: Chris@439: SimpleSPARQLQuery::Impl::Impl(QString query) : Chris@439: m_query(query), Chris@439: m_reporter(0), Chris@439: m_cancelled(false) Chris@439: { Chris@457: // std::cerr << "SimpleSPARQLQuery::Impl: Query is: \"" << query.toStdString() << "\"" << std::endl; Chris@439: } Chris@439: Chris@439: SimpleSPARQLQuery::Impl::~Impl() Chris@439: { Chris@439: } Chris@439: Chris@439: bool Chris@439: SimpleSPARQLQuery::Impl::isOK() const Chris@439: { Chris@439: return (m_errorString == ""); Chris@439: } Chris@439: Chris@439: QString Chris@439: SimpleSPARQLQuery::Impl::getErrorString() const Chris@439: { Chris@439: return m_errorString; Chris@439: } Chris@439: Chris@439: void Chris@439: SimpleSPARQLQuery::Impl::errorHandler(void *data, Chris@439: raptor_locator *locator, Chris@439: const char *message) Chris@439: { Chris@439: SimpleSPARQLQuery::Impl *impl = (SimpleSPARQLQuery::Impl *)data; Chris@439: Chris@439: // char buffer[256]; Chris@439: // raptor_format_locator(buffer, 255, locator); Chris@439: // impl->m_errorString = QString("%1 - %2").arg(buffer).arg(message); Chris@439: Chris@439: impl->m_errorString = message; Chris@439: Chris@439: cerr << "SimpleSPARQLQuery: ERROR: " << impl->m_errorString.toStdString() << endl; Chris@439: } Chris@439: Chris@439: SimpleSPARQLQuery::ResultList Chris@439: SimpleSPARQLQuery::Impl::execute() Chris@439: { Chris@439: ResultList list; Chris@439: Chris@440: #ifdef USE_NEW_RASQAL_API Chris@440: rasqal_query *query = rasqal_new_query(m_www.getWorld(), "sparql", NULL); Chris@440: #else Chris@440: if (!m_initialised) { Chris@440: m_initialised = true; Chris@440: rasqal_init(); Chris@440: } Chris@439: rasqal_query *query = rasqal_new_query("sparql", NULL); Chris@440: #endif Chris@439: if (!query) { Chris@439: m_errorString = "Failed to construct query"; Chris@439: cerr << "SimpleSPARQLQuery: ERROR: " << m_errorString.toStdString() << endl; Chris@439: return list; Chris@439: } Chris@439: Chris@439: rasqal_query_set_error_handler(query, this, errorHandler); Chris@439: rasqal_query_set_fatal_error_handler(query, this, errorHandler); Chris@439: Chris@439: if (rasqal_query_prepare Chris@439: (query, (const unsigned char *)m_query.toUtf8().data(), NULL)) { Chris@439: cerr << "SimpleSPARQLQuery: Failed to prepare query" << endl; Chris@439: rasqal_free_query(query); Chris@439: return list; Chris@439: } Chris@439: Chris@439: rasqal_query_results *results = rasqal_query_execute(query); Chris@439: Chris@439: // cerr << "Query executed" << endl; Chris@439: Chris@439: if (!results) { Chris@439: cerr << "SimpleSPARQLQuery: RASQAL query failed" << endl; Chris@439: rasqal_free_query(query); Chris@439: return list; Chris@439: } Chris@439: Chris@439: if (!rasqal_query_results_is_bindings(results)) { Chris@439: cerr << "SimpleSPARQLQuery: RASQAL query has wrong result type (not bindings)" << endl; Chris@439: rasqal_free_query_results(results); Chris@439: rasqal_free_query(query); Chris@439: return list; Chris@439: } Chris@439: Chris@439: int resultCount = 0; Chris@439: int resultTotal = rasqal_query_results_get_count(results); // probably wrong Chris@439: m_cancelled = false; Chris@439: Chris@439: while (!rasqal_query_results_finished(results)) { Chris@439: Chris@439: int count = rasqal_query_results_get_bindings_count(results); Chris@439: Chris@439: KeyValueMap resultmap; Chris@439: Chris@439: for (int i = 0; i < count; ++i) { Chris@439: Chris@439: const unsigned char *name = Chris@439: rasqal_query_results_get_binding_name(results, i); Chris@439: Chris@439: rasqal_literal *literal = Chris@439: rasqal_query_results_get_binding_value(results, i); Chris@439: Chris@439: QString key = (const char *)name; Chris@439: Chris@439: if (!literal) { Chris@439: resultmap[key] = Value(); Chris@439: continue; Chris@439: } Chris@439: Chris@439: ValueType type = LiteralValue; Chris@439: if (literal->type == RASQAL_LITERAL_URI) type = URIValue; Chris@439: else if (literal->type == RASQAL_LITERAL_BLANK) type = BlankValue; Chris@439: Chris@439: QString text = (const char *)rasqal_literal_as_string(literal); Chris@439: Chris@449: std::cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << std::endl; Chris@449: Chris@439: resultmap[key] = Value(type, text); Chris@439: } Chris@439: Chris@439: list.push_back(resultmap); Chris@439: Chris@439: rasqal_query_results_next(results); Chris@439: Chris@439: resultCount++; Chris@439: Chris@439: if (m_reporter) { Chris@439: if (resultCount >= resultTotal) { Chris@439: if (m_reporter->isDefinite()) m_reporter->setDefinite(false); Chris@439: m_reporter->setProgress(resultCount); Chris@439: } else { Chris@439: m_reporter->setProgress((resultCount * 100) / resultTotal); Chris@439: } Chris@439: Chris@439: if (m_reporter->wasCancelled()) { Chris@439: m_cancelled = true; Chris@439: break; Chris@439: } Chris@439: } Chris@439: } Chris@439: Chris@439: rasqal_free_query_results(results); Chris@439: rasqal_free_query(query); Chris@439: Chris@439: return list; Chris@439: } Chris@440: Chris@440: SimpleSPARQLQuery::Value Chris@440: SimpleSPARQLQuery::singleResultQuery(QString query, QString binding) Chris@440: { Chris@440: SimpleSPARQLQuery q(query); Chris@440: ResultList results = q.execute(); Chris@440: if (!q.isOK()) { Chris@440: cerr << "SimpleSPARQLQuery::singleResultQuery: ERROR: " Chris@440: << q.getErrorString().toStdString() << endl; Chris@440: return Value(); Chris@440: } Chris@440: if (results.empty()) { Chris@440: return Value(); Chris@440: } Chris@440: for (int i = 0; i < results.size(); ++i) { Chris@440: if (results[i].find(binding) != results[i].end() && Chris@440: results[i][binding].type != NoValue) { Chris@440: return results[i][binding]; Chris@440: } Chris@440: } Chris@440: return Value(); Chris@440: } Chris@440: Chris@440: Chris@440: