Mercurial > hg > svcore
diff rdf/SimpleSPARQLQuery.cpp @ 439:beb2948baa77
* Merge revisions 1041 to 1130 from sv-rdf-import branch
author | Chris Cannam |
---|---|
date | Thu, 18 Sep 2008 12:09:32 +0000 |
parents | |
children | 5746c559af15 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rdf/SimpleSPARQLQuery.cpp Thu Sep 18 12:09:32 2008 +0000 @@ -0,0 +1,235 @@ +/* -*- 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 "SimpleSPARQLQuery.h" +#include "base/ProgressReporter.h" + +#include <rasqal.h> + +#include <iostream> + +using std::cerr; +using std::endl; + +class SimpleSPARQLQuery::Impl +{ +public: + Impl(QString query); + ~Impl(); + + void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; } + bool wasCancelled() const { return m_cancelled; } + + ResultList execute(); + + bool isOK() const; + QString getErrorString() const; + +protected: + static void errorHandler(void *, raptor_locator *, const char *); + + static bool m_initialised; + + QString m_query; + QString m_errorString; + ProgressReporter *m_reporter; + bool m_cancelled; +}; + +SimpleSPARQLQuery::SimpleSPARQLQuery(QString query) : + m_impl(new Impl(query)) { } + +SimpleSPARQLQuery::~SimpleSPARQLQuery() +{ + delete m_impl; +} + +void +SimpleSPARQLQuery::setProgressReporter(ProgressReporter *reporter) +{ + m_impl->setProgressReporter(reporter); +} + +bool +SimpleSPARQLQuery::wasCancelled() const +{ + return m_impl->wasCancelled(); +} + +SimpleSPARQLQuery::ResultList +SimpleSPARQLQuery::execute() +{ + return m_impl->execute(); +} + +bool +SimpleSPARQLQuery::isOK() const +{ + return m_impl->isOK(); +} + +QString +SimpleSPARQLQuery::getErrorString() const +{ + return m_impl->getErrorString(); +} + +bool +SimpleSPARQLQuery::Impl::m_initialised = false; + +SimpleSPARQLQuery::Impl::Impl(QString query) : + m_query(query), + m_reporter(0), + m_cancelled(false) +{ + //!!! fortunately this global stuff goes away in future rasqal versions + if (!m_initialised) { + rasqal_init(); + } +} + +SimpleSPARQLQuery::Impl::~Impl() +{ +//!!! rasqal_finish(); +} + +bool +SimpleSPARQLQuery::Impl::isOK() const +{ + return (m_errorString == ""); +} + +QString +SimpleSPARQLQuery::Impl::getErrorString() const +{ + return m_errorString; +} + +void +SimpleSPARQLQuery::Impl::errorHandler(void *data, + raptor_locator *locator, + const char *message) +{ + SimpleSPARQLQuery::Impl *impl = (SimpleSPARQLQuery::Impl *)data; + +// char buffer[256]; +// raptor_format_locator(buffer, 255, locator); +// impl->m_errorString = QString("%1 - %2").arg(buffer).arg(message); + + impl->m_errorString = message; + + cerr << "SimpleSPARQLQuery: ERROR: " << impl->m_errorString.toStdString() << endl; +} + +SimpleSPARQLQuery::ResultList +SimpleSPARQLQuery::Impl::execute() +{ + ResultList list; + + rasqal_query *query = rasqal_new_query("sparql", NULL); + if (!query) { + m_errorString = "Failed to construct query"; + cerr << "SimpleSPARQLQuery: ERROR: " << m_errorString.toStdString() << endl; + return list; + } + + rasqal_query_set_error_handler(query, this, errorHandler); + rasqal_query_set_fatal_error_handler(query, this, errorHandler); + + if (rasqal_query_prepare + (query, (const unsigned char *)m_query.toUtf8().data(), NULL)) { + cerr << "SimpleSPARQLQuery: Failed to prepare query" << endl; + rasqal_free_query(query); + return list; + } + + rasqal_query_results *results = rasqal_query_execute(query); + +// cerr << "Query executed" << endl; + + if (!results) { + cerr << "SimpleSPARQLQuery: RASQAL query failed" << endl; + rasqal_free_query(query); + return list; + } + + if (!rasqal_query_results_is_bindings(results)) { + cerr << "SimpleSPARQLQuery: RASQAL query has wrong result type (not bindings)" << endl; + rasqal_free_query_results(results); + rasqal_free_query(query); + return list; + } + + int resultCount = 0; + int resultTotal = rasqal_query_results_get_count(results); // probably wrong + m_cancelled = false; + + while (!rasqal_query_results_finished(results)) { + + int count = rasqal_query_results_get_bindings_count(results); + + KeyValueMap resultmap; + + for (int i = 0; i < count; ++i) { + + const unsigned char *name = + rasqal_query_results_get_binding_name(results, i); + + rasqal_literal *literal = + rasqal_query_results_get_binding_value(results, i); + + QString key = (const char *)name; + + if (!literal) { + resultmap[key] = Value(); + continue; + } + + ValueType type = LiteralValue; + if (literal->type == RASQAL_LITERAL_URI) type = URIValue; + else if (literal->type == RASQAL_LITERAL_BLANK) type = BlankValue; + + QString text = (const char *)rasqal_literal_as_string(literal); + + resultmap[key] = Value(type, text); + } + + list.push_back(resultmap); + + rasqal_query_results_next(results); + + resultCount++; + + if (m_reporter) { + if (resultCount >= resultTotal) { + if (m_reporter->isDefinite()) m_reporter->setDefinite(false); + m_reporter->setProgress(resultCount); + } else { + m_reporter->setProgress((resultCount * 100) / resultTotal); + } + + if (m_reporter->wasCancelled()) { + m_cancelled = true; + break; + } + } + } + + rasqal_free_query_results(results); + rasqal_free_query(query); + + return list; +} +