annotate rdf/SimpleSPARQLQuery.cpp @ 490:c3fb8258e34d

* Make it possible to import an entire session from an RDF document. However, at the moment the timings of events appear to be constrained by how far the audio decoder has got through its audio file at the time the event is queried -- need to investigate.
author Chris Cannam
date Fri, 21 Nov 2008 18:03:14 +0000
parents 82ab61fa9223
children 23945cdd7161
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 "SimpleSPARQLQuery.h"
Chris@439 17 #include "base/ProgressReporter.h"
Chris@480 18 #include "base/Profiler.h"
Chris@480 19
Chris@480 20 #include <QMutex>
Chris@480 21 #include <QMutexLocker>
Chris@481 22 #include <QRegExp>
Chris@480 23
Chris@480 24 #include <set>
Chris@439 25
Chris@440 26 #ifdef USE_NEW_RASQAL_API
Chris@440 27 #include <rasqal/rasqal.h>
Chris@440 28 #else
Chris@439 29 #include <rasqal.h>
Chris@440 30 #endif
Chris@439 31
Chris@480 32 #include <redland.h>
Chris@480 33
Chris@490 34 #define DEBUG_SIMPLE_SPARQL_QUERY 1
Chris@461 35
Chris@439 36 #include <iostream>
Chris@439 37
Chris@439 38 using std::cerr;
Chris@439 39 using std::endl;
Chris@439 40
Chris@440 41 #ifdef USE_NEW_RASQAL_API
Chris@440 42 class WrasqalWorldWrapper // wrong but wromantic, etc
Chris@440 43 {
Chris@440 44 public:
Chris@481 45 WrasqalWorldWrapper() :
Chris@481 46 m_world(0)
Chris@481 47 {
Chris@481 48 m_world = rasqal_new_world();
Chris@481 49 if (!m_world) {
Chris@481 50 cerr << "SimpleSPARQLQuery: ERROR: Failed to create RASQAL world!" << endl;
Chris@481 51 return;
Chris@481 52 }
Chris@481 53 /*!!! This appears to be new for 0.9.17?
Chris@481 54 if (rasqal_world_open(m_world)) {
Chris@481 55 cerr << "SimpleSPARQLQuery: ERROR: Failed to open RASQAL world!" << endl;
Chris@481 56 return;
Chris@481 57 }
Chris@481 58 */
Chris@481 59 }
Chris@481 60 ~WrasqalWorldWrapper()
Chris@481 61 {
Chris@481 62 rasqal_free_world(m_world);
Chris@481 63 }
Chris@440 64
Chris@489 65 bool isOK() const { return (m_world != 0); }
Chris@489 66
Chris@480 67 rasqal_world *getWorld() { return m_world; }
Chris@480 68 const rasqal_world *getWorld() const { return m_world; }
Chris@440 69
Chris@440 70 private:
Chris@440 71 rasqal_world *m_world;
Chris@440 72 };
Chris@440 73 #endif
Chris@440 74
Chris@480 75 class WredlandWorldWrapper
Chris@480 76 {
Chris@480 77 public:
Chris@480 78 WredlandWorldWrapper() :
Chris@480 79 m_world(0), m_storage(0), m_model(0)
Chris@480 80 {
Chris@480 81 m_world = librdf_new_world();
Chris@481 82 if (!m_world) {
Chris@481 83 cerr << "SimpleSPARQLQuery: ERROR: Failed to create LIBRDF world!" << endl;
Chris@481 84 return;
Chris@481 85 }
Chris@480 86 librdf_world_open(m_world);
Chris@481 87 m_storage = librdf_new_storage(m_world, "trees", NULL, NULL);
Chris@480 88 if (!m_storage) {
Chris@481 89 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland trees datastore, falling back to memory store" << std::endl;
Chris@480 90 m_storage = librdf_new_storage(m_world, NULL, NULL, NULL);
Chris@480 91 if (!m_storage) {
Chris@480 92 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland memory datastore" << std::endl;
Chris@480 93 return;
Chris@480 94 }
Chris@480 95 }
Chris@480 96 m_model = librdf_new_model(m_world, m_storage, NULL);
Chris@480 97 if (!m_model) {
Chris@480 98 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland data model" << std::endl;
Chris@480 99 return;
Chris@480 100 }
Chris@480 101 }
Chris@480 102
Chris@480 103 ~WredlandWorldWrapper()
Chris@480 104 {
Chris@480 105 while (!m_parsedUris.empty()) {
Chris@480 106 librdf_free_uri(m_parsedUris.begin()->second);
Chris@480 107 m_parsedUris.erase(m_parsedUris.begin());
Chris@480 108 }
Chris@480 109 if (m_model) librdf_free_model(m_model);
Chris@480 110 if (m_storage) librdf_free_storage(m_storage);
Chris@480 111 if (m_world) librdf_free_world(m_world);
Chris@480 112 }
Chris@480 113
Chris@480 114 bool isOK() const { return (m_model != 0); }
Chris@480 115
Chris@480 116 librdf_uri *getUri(QString uriString, QString &errorString)
Chris@480 117 {
Chris@480 118 if (m_parsedUris.find(uriString) != m_parsedUris.end()) {
Chris@480 119 return m_parsedUris[uriString];
Chris@480 120 }
Chris@480 121
Chris@480 122 librdf_uri *uri = librdf_new_uri
Chris@480 123 (m_world, (const unsigned char *)uriString.toUtf8().data());
Chris@480 124 if (!uri) {
Chris@480 125 errorString = "Failed to construct librdf_uri!";
Chris@480 126 return 0;
Chris@480 127 }
Chris@480 128
Chris@480 129 librdf_parser *parser = librdf_new_parser(m_world, "guess", NULL, NULL);
Chris@480 130 if (!parser) {
Chris@480 131 errorString = "Failed to initialise Redland parser";
Chris@480 132 return 0;
Chris@480 133 }
Chris@480 134
Chris@480 135 std::cerr << "About to parse \"" << uriString.toStdString() << "\"" << std::endl;
Chris@480 136
Chris@480 137 Profiler p("SimpleSPARQLQuery: Parse URI into LIBRDF model");
Chris@480 138
Chris@480 139 if (librdf_parser_parse_into_model(parser, uri, NULL, m_model)) {
Chris@480 140
Chris@480 141 errorString = QString("Failed to parse RDF from URI \"%1\"")
Chris@480 142 .arg(uriString);
Chris@480 143 librdf_free_parser(parser);
Chris@490 144 // librdf_free_uri(uri);
Chris@480 145 return 0;
Chris@480 146
Chris@480 147 } else {
Chris@480 148
Chris@480 149 librdf_free_parser(parser);
Chris@480 150 m_parsedUris[uriString] = uri;
Chris@480 151 return uri;
Chris@480 152 }
Chris@480 153 }
Chris@480 154
Chris@480 155 librdf_world *getWorld() { return m_world; }
Chris@480 156 const librdf_world *getWorld() const { return m_world; }
Chris@480 157
Chris@480 158 librdf_model *getModel() { return m_model; }
Chris@480 159 const librdf_model *getModel() const { return m_model; }
Chris@480 160
Chris@480 161 private:
Chris@480 162 librdf_world *m_world;
Chris@480 163 librdf_storage *m_storage;
Chris@480 164 librdf_model *m_model;
Chris@480 165
Chris@480 166 QMutex m_mutex;
Chris@480 167 std::map<QString, librdf_uri *> m_parsedUris;
Chris@480 168 };
Chris@480 169
Chris@439 170 class SimpleSPARQLQuery::Impl
Chris@439 171 {
Chris@439 172 public:
Chris@489 173 Impl(SimpleSPARQLQuery::QueryType, QString query);
Chris@439 174 ~Impl();
Chris@439 175
Chris@489 176 static bool addSourceToModel(QString sourceUri);
Chris@489 177
Chris@439 178 void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; }
Chris@439 179 bool wasCancelled() const { return m_cancelled; }
Chris@439 180
Chris@439 181 ResultList execute();
Chris@439 182
Chris@439 183 bool isOK() const;
Chris@439 184 QString getErrorString() const;
Chris@439 185
Chris@439 186 protected:
Chris@439 187 static void errorHandler(void *, raptor_locator *, const char *);
Chris@439 188
Chris@480 189 static QMutex m_mutex;
Chris@480 190
Chris@440 191 #ifdef USE_NEW_RASQAL_API
Chris@480 192 static WrasqalWorldWrapper *m_rasqal;
Chris@440 193 #else
Chris@480 194 static bool m_rasqalInitialised;
Chris@440 195 #endif
Chris@480 196
Chris@480 197 static WredlandWorldWrapper *m_redland;
Chris@480 198
Chris@480 199 ResultList executeDirectParser();
Chris@480 200 ResultList executeDatastore();
Chris@480 201
Chris@489 202 QueryType m_type;
Chris@439 203 QString m_query;
Chris@439 204 QString m_errorString;
Chris@439 205 ProgressReporter *m_reporter;
Chris@439 206 bool m_cancelled;
Chris@439 207 };
Chris@439 208
Chris@440 209 #ifdef USE_NEW_RASQAL_API
Chris@480 210 WrasqalWorldWrapper *SimpleSPARQLQuery::Impl::m_rasqal = 0;
Chris@440 211 #else
Chris@480 212 bool SimpleSPARQLQuery::Impl::m_rasqalInitialised = false;
Chris@440 213 #endif
Chris@440 214
Chris@480 215 WredlandWorldWrapper *SimpleSPARQLQuery::Impl::m_redland = 0;
Chris@480 216
Chris@480 217 QMutex SimpleSPARQLQuery::Impl::m_mutex;
Chris@480 218
Chris@489 219 SimpleSPARQLQuery::SimpleSPARQLQuery(QueryType type, QString query) :
Chris@489 220 m_impl(new Impl(type, query))
Chris@480 221 {
Chris@480 222 }
Chris@439 223
Chris@439 224 SimpleSPARQLQuery::~SimpleSPARQLQuery()
Chris@439 225 {
Chris@439 226 delete m_impl;
Chris@439 227 }
Chris@439 228
Chris@439 229 void
Chris@439 230 SimpleSPARQLQuery::setProgressReporter(ProgressReporter *reporter)
Chris@439 231 {
Chris@439 232 m_impl->setProgressReporter(reporter);
Chris@439 233 }
Chris@439 234
Chris@439 235 bool
Chris@439 236 SimpleSPARQLQuery::wasCancelled() const
Chris@439 237 {
Chris@439 238 return m_impl->wasCancelled();
Chris@439 239 }
Chris@439 240
Chris@439 241 SimpleSPARQLQuery::ResultList
Chris@439 242 SimpleSPARQLQuery::execute()
Chris@439 243 {
Chris@439 244 return m_impl->execute();
Chris@439 245 }
Chris@439 246
Chris@439 247 bool
Chris@439 248 SimpleSPARQLQuery::isOK() const
Chris@439 249 {
Chris@439 250 return m_impl->isOK();
Chris@439 251 }
Chris@439 252
Chris@439 253 QString
Chris@439 254 SimpleSPARQLQuery::getErrorString() const
Chris@439 255 {
Chris@439 256 return m_impl->getErrorString();
Chris@439 257 }
Chris@439 258
Chris@489 259 bool
Chris@489 260 SimpleSPARQLQuery::addSourceToModel(QString sourceUri)
Chris@480 261 {
Chris@489 262 return SimpleSPARQLQuery::Impl::addSourceToModel(sourceUri);
Chris@480 263 }
Chris@480 264
Chris@489 265 SimpleSPARQLQuery::Impl::Impl(QueryType type, QString query) :
Chris@489 266 m_type(type),
Chris@439 267 m_query(query),
Chris@439 268 m_reporter(0),
Chris@439 269 m_cancelled(false)
Chris@439 270 {
Chris@461 271 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@461 272 std::cerr << "SimpleSPARQLQuery::Impl: Query is: \"" << query.toStdString() << "\"" << std::endl;
Chris@461 273 #endif
Chris@439 274 }
Chris@439 275
Chris@439 276 SimpleSPARQLQuery::Impl::~Impl()
Chris@439 277 {
Chris@439 278 }
Chris@439 279
Chris@439 280 bool
Chris@439 281 SimpleSPARQLQuery::Impl::isOK() const
Chris@439 282 {
Chris@439 283 return (m_errorString == "");
Chris@439 284 }
Chris@439 285
Chris@439 286 QString
Chris@439 287 SimpleSPARQLQuery::Impl::getErrorString() const
Chris@439 288 {
Chris@439 289 return m_errorString;
Chris@439 290 }
Chris@439 291
Chris@439 292 void
Chris@439 293 SimpleSPARQLQuery::Impl::errorHandler(void *data,
Chris@439 294 raptor_locator *locator,
Chris@439 295 const char *message)
Chris@439 296 {
Chris@439 297 SimpleSPARQLQuery::Impl *impl = (SimpleSPARQLQuery::Impl *)data;
Chris@439 298
Chris@481 299 char buffer[256];
Chris@481 300 raptor_format_locator(buffer, 255, locator);
Chris@481 301 QString loc(buffer);
Chris@481 302 if (loc != "") {
Chris@481 303 impl->m_errorString = QString("%1 - %2").arg(loc).arg(message);
Chris@481 304 } else {
Chris@481 305 impl->m_errorString = message;
Chris@481 306 }
Chris@439 307
Chris@439 308 cerr << "SimpleSPARQLQuery: ERROR: " << impl->m_errorString.toStdString() << endl;
Chris@439 309 }
Chris@439 310
Chris@439 311 SimpleSPARQLQuery::ResultList
Chris@439 312 SimpleSPARQLQuery::Impl::execute()
Chris@439 313 {
Chris@439 314 ResultList list;
Chris@439 315
Chris@490 316 QMutexLocker locker(&m_mutex);
Chris@480 317
Chris@489 318 if (m_type == QueryFromModel) {
Chris@489 319 if (!m_redland) {
Chris@489 320 // There can be no results, because no sources have been
Chris@489 321 // added to the model yet (m_redland is only created when
Chris@489 322 // addSourceToModel is called)
Chris@489 323 cerr << "SimpleSPARQLQuery::execute: NOTE: No sources have been added to data model yet, so no results are possible" << endl;
Chris@489 324 return list;
Chris@481 325 }
Chris@481 326 }
Chris@481 327
Chris@489 328 if (m_type == QueryFromSingleSource) {
Chris@489 329 #ifdef USE_NEW_RASQAL_API
Chris@489 330 if (!m_rasqal) {
Chris@489 331 m_rasqal = new WrasqalWorldWrapper();
Chris@489 332 if (!m_rasqal->isOK()) {
Chris@489 333 cerr << "ERROR: SimpleSPARQLQuery::execute: Failed to initialise Rasqal query engine" << endl;
Chris@489 334 delete m_rasqal;
Chris@489 335 m_rasqal = 0;
Chris@489 336 return list;
Chris@480 337 }
Chris@480 338 }
Chris@480 339 #else
Chris@480 340 if (!m_rasqalInitialised) {
Chris@480 341 rasqal_init();
Chris@480 342 m_rasqalInitialised = true;
Chris@480 343 }
Chris@480 344 #endif
Chris@440 345 }
Chris@480 346
Chris@489 347 if (m_type == QueryFromSingleSource) {
Chris@480 348 return executeDirectParser();
Chris@480 349 } else {
Chris@480 350 return executeDatastore();
Chris@480 351 }
Chris@480 352 }
Chris@480 353
Chris@480 354 SimpleSPARQLQuery::ResultList
Chris@480 355 SimpleSPARQLQuery::Impl::executeDirectParser()
Chris@480 356 {
Chris@480 357 ResultList list;
Chris@480 358
Chris@480 359 Profiler profiler("SimpleSPARQLQuery::executeDirectParser");
Chris@480 360
Chris@480 361 #ifdef USE_NEW_RASQAL_API
Chris@480 362 rasqal_query *query = rasqal_new_query(m_rasqal->getWorld(), "sparql", NULL);
Chris@480 363 #else
Chris@439 364 rasqal_query *query = rasqal_new_query("sparql", NULL);
Chris@440 365 #endif
Chris@439 366 if (!query) {
Chris@439 367 m_errorString = "Failed to construct query";
Chris@439 368 cerr << "SimpleSPARQLQuery: ERROR: " << m_errorString.toStdString() << endl;
Chris@439 369 return list;
Chris@439 370 }
Chris@439 371
Chris@439 372 rasqal_query_set_error_handler(query, this, errorHandler);
Chris@439 373 rasqal_query_set_fatal_error_handler(query, this, errorHandler);
Chris@439 374
Chris@480 375 {
Chris@480 376 Profiler p("SimpleSPARQLQuery: Prepare RASQAL query");
Chris@480 377
Chris@480 378 if (rasqal_query_prepare
Chris@480 379 (query, (const unsigned char *)m_query.toUtf8().data(), NULL)) {
Chris@480 380 cerr << "SimpleSPARQLQuery: Failed to prepare query" << endl;
Chris@480 381 rasqal_free_query(query);
Chris@480 382 return list;
Chris@480 383 }
Chris@439 384 }
Chris@439 385
Chris@480 386 rasqal_query_results *results;
Chris@480 387
Chris@480 388 {
Chris@480 389 Profiler p("SimpleSPARQLQuery: Execute RASQAL query");
Chris@480 390 results = rasqal_query_execute(query);
Chris@480 391 }
Chris@439 392
Chris@439 393 // cerr << "Query executed" << endl;
Chris@439 394
Chris@439 395 if (!results) {
Chris@439 396 cerr << "SimpleSPARQLQuery: RASQAL query failed" << endl;
Chris@439 397 rasqal_free_query(query);
Chris@439 398 return list;
Chris@439 399 }
Chris@439 400
Chris@439 401 if (!rasqal_query_results_is_bindings(results)) {
Chris@439 402 cerr << "SimpleSPARQLQuery: RASQAL query has wrong result type (not bindings)" << endl;
Chris@439 403 rasqal_free_query_results(results);
Chris@439 404 rasqal_free_query(query);
Chris@439 405 return list;
Chris@439 406 }
Chris@439 407
Chris@439 408 int resultCount = 0;
Chris@439 409 int resultTotal = rasqal_query_results_get_count(results); // probably wrong
Chris@439 410 m_cancelled = false;
Chris@439 411
Chris@439 412 while (!rasqal_query_results_finished(results)) {
Chris@439 413
Chris@439 414 int count = rasqal_query_results_get_bindings_count(results);
Chris@439 415
Chris@439 416 KeyValueMap resultmap;
Chris@439 417
Chris@439 418 for (int i = 0; i < count; ++i) {
Chris@439 419
Chris@439 420 const unsigned char *name =
Chris@439 421 rasqal_query_results_get_binding_name(results, i);
Chris@439 422
Chris@490 423 if (!name) {
Chris@490 424 std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl;
Chris@490 425 continue;
Chris@490 426 }
Chris@490 427
Chris@439 428 rasqal_literal *literal =
Chris@439 429 rasqal_query_results_get_binding_value(results, i);
Chris@439 430
Chris@439 431 QString key = (const char *)name;
Chris@439 432
Chris@439 433 if (!literal) {
Chris@439 434 resultmap[key] = Value();
Chris@439 435 continue;
Chris@439 436 }
Chris@439 437
Chris@439 438 ValueType type = LiteralValue;
Chris@490 439 if (literal->type == RASQAL_LITERAL_BLANK) type = BlankValue;
Chris@490 440 else if (literal->type == RASQAL_LITERAL_URI) type = URIValue;
Chris@439 441
Chris@490 442 QString text;
Chris@490 443 const char *lit = (const char *)rasqal_literal_as_string(literal);
Chris@490 444 if (!lit) {
Chris@490 445 std::cerr << "WARNING: Result " << i << " of query has null value" << std::endl;
Chris@490 446 } else {
Chris@490 447 text = lit;
Chris@490 448 }
Chris@439 449
Chris@461 450 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@449 451 std::cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << std::endl;
Chris@461 452 #endif
Chris@449 453
Chris@439 454 resultmap[key] = Value(type, text);
Chris@439 455 }
Chris@439 456
Chris@439 457 list.push_back(resultmap);
Chris@439 458
Chris@439 459 rasqal_query_results_next(results);
Chris@439 460
Chris@439 461 resultCount++;
Chris@439 462
Chris@439 463 if (m_reporter) {
Chris@439 464 if (resultCount >= resultTotal) {
Chris@439 465 if (m_reporter->isDefinite()) m_reporter->setDefinite(false);
Chris@439 466 m_reporter->setProgress(resultCount);
Chris@439 467 } else {
Chris@439 468 m_reporter->setProgress((resultCount * 100) / resultTotal);
Chris@439 469 }
Chris@439 470
Chris@439 471 if (m_reporter->wasCancelled()) {
Chris@439 472 m_cancelled = true;
Chris@439 473 break;
Chris@439 474 }
Chris@439 475 }
Chris@439 476 }
Chris@439 477
Chris@439 478 rasqal_free_query_results(results);
Chris@439 479 rasqal_free_query(query);
Chris@439 480
Chris@439 481 return list;
Chris@439 482 }
Chris@440 483
Chris@480 484 SimpleSPARQLQuery::ResultList
Chris@480 485 SimpleSPARQLQuery::Impl::executeDatastore()
Chris@480 486 {
Chris@480 487 ResultList list;
Chris@489 488
Chris@480 489 Profiler profiler("SimpleSPARQLQuery::executeDatastore");
Chris@480 490
Chris@481 491 /*!!!
Chris@480 492 static std::map<QString, int> counter;
Chris@480 493 if (counter.find(m_query) == counter.end()) counter[m_query] = 1;
Chris@480 494 else ++counter[m_query];
Chris@480 495 std::cerr << "Counter for this query: " << counter[m_query] << std::endl;
Chris@481 496 std::cerr << "Base URI is: \"" << m_fromUri.toStdString() << "\"" << std::endl;
Chris@481 497 */
Chris@480 498
Chris@480 499 librdf_query *query;
Chris@480 500
Chris@480 501 {
Chris@480 502 Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query");
Chris@480 503 query = librdf_new_query
Chris@480 504 (m_redland->getWorld(), "sparql", NULL,
Chris@489 505 (const unsigned char *)m_query.toUtf8().data(), NULL);
Chris@480 506 }
Chris@480 507
Chris@480 508 if (!query) {
Chris@480 509 m_errorString = "Failed to construct query";
Chris@480 510 return list;
Chris@480 511 }
Chris@480 512
Chris@480 513 librdf_query_results *results;
Chris@480 514 {
Chris@480 515 Profiler p("SimpleSPARQLQuery: Execute LIBRDF query");
Chris@480 516 results = librdf_query_execute(query, m_redland->getModel());
Chris@480 517 }
Chris@480 518
Chris@480 519 if (!results) {
Chris@480 520 cerr << "SimpleSPARQLQuery: LIBRDF query failed" << endl;
Chris@480 521 librdf_free_query(query);
Chris@480 522 return list;
Chris@480 523 }
Chris@480 524
Chris@480 525 if (!librdf_query_results_is_bindings(results)) {
Chris@480 526 cerr << "SimpleSPARQLQuery: LIBRDF query has wrong result type (not bindings)" << endl;
Chris@480 527 librdf_free_query_results(results);
Chris@480 528 librdf_free_query(query);
Chris@480 529 return list;
Chris@480 530 }
Chris@480 531
Chris@480 532 int resultCount = 0;
Chris@480 533 int resultTotal = librdf_query_results_get_count(results); // probably wrong
Chris@480 534 m_cancelled = false;
Chris@480 535
Chris@480 536 while (!librdf_query_results_finished(results)) {
Chris@480 537
Chris@480 538 int count = librdf_query_results_get_bindings_count(results);
Chris@480 539
Chris@480 540 KeyValueMap resultmap;
Chris@480 541
Chris@480 542 for (int i = 0; i < count; ++i) {
Chris@480 543
Chris@480 544 const char *name =
Chris@480 545 librdf_query_results_get_binding_name(results, i);
Chris@480 546
Chris@490 547 if (!name) {
Chris@490 548 std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl;
Chris@490 549 continue;
Chris@490 550 }
Chris@490 551
Chris@480 552 librdf_node *node =
Chris@480 553 librdf_query_results_get_binding_value(results, i);
Chris@480 554
Chris@480 555 QString key = (const char *)name;
Chris@480 556
Chris@480 557 if (!node) {
Chris@480 558 resultmap[key] = Value();
Chris@480 559 continue;
Chris@480 560 }
Chris@480 561
Chris@480 562 ValueType type = LiteralValue;
Chris@481 563 QString text;
Chris@481 564
Chris@481 565 if (librdf_node_is_resource(node)) {
Chris@481 566
Chris@481 567 type = URIValue;
Chris@481 568 librdf_uri *uri = librdf_node_get_uri(node);
Chris@490 569 const char *us = (const char *)librdf_uri_as_string(uri);
Chris@490 570
Chris@490 571 if (!us) {
Chris@490 572 std::cerr << "WARNING: Result " << i << " of query claims URI type, but has null URI" << std::endl;
Chris@490 573 } else {
Chris@490 574 text = us;
Chris@490 575 }
Chris@481 576
Chris@481 577 } else if (librdf_node_is_literal(node)) {
Chris@481 578
Chris@481 579 type = LiteralValue;
Chris@490 580
Chris@490 581 const char *lit = (const char *)librdf_node_get_literal_value(node);
Chris@490 582 if (!lit) {
Chris@490 583 std::cerr << "WARNING: Result " << i << " of query claims literal type, but has no literal" << std::endl;
Chris@490 584 } else {
Chris@490 585 text = lit;
Chris@490 586 }
Chris@481 587
Chris@481 588 } else if (librdf_node_is_blank(node)) {
Chris@481 589
Chris@481 590 type = BlankValue;
Chris@481 591
Chris@481 592 } else {
Chris@481 593
Chris@480 594 cerr << "SimpleSPARQLQuery: LIBRDF query returned unknown node type (not resource, literal, or blank)" << endl;
Chris@480 595 }
Chris@480 596
Chris@480 597 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@481 598 cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << endl;
Chris@480 599 #endif
Chris@480 600
Chris@480 601 resultmap[key] = Value(type, text);
Chris@480 602
Chris@480 603 librdf_free_node(node);
Chris@480 604 }
Chris@480 605
Chris@480 606 list.push_back(resultmap);
Chris@480 607
Chris@480 608 librdf_query_results_next(results);
Chris@480 609
Chris@480 610 resultCount++;
Chris@480 611
Chris@480 612 if (m_reporter) {
Chris@480 613 if (resultCount >= resultTotal) {
Chris@480 614 if (m_reporter->isDefinite()) m_reporter->setDefinite(false);
Chris@480 615 m_reporter->setProgress(resultCount);
Chris@480 616 } else {
Chris@480 617 m_reporter->setProgress((resultCount * 100) / resultTotal);
Chris@480 618 }
Chris@480 619
Chris@480 620 if (m_reporter->wasCancelled()) {
Chris@480 621 m_cancelled = true;
Chris@480 622 break;
Chris@480 623 }
Chris@480 624 }
Chris@480 625 }
Chris@480 626
Chris@480 627 librdf_free_query_results(results);
Chris@480 628 librdf_free_query(query);
Chris@480 629
Chris@481 630 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@481 631 cerr << "All results retrieved (" << resultCount << " of them)" << endl;
Chris@481 632 #endif
Chris@480 633
Chris@480 634 return list;
Chris@489 635 }
Chris@489 636
Chris@489 637 bool
Chris@489 638 SimpleSPARQLQuery::Impl::addSourceToModel(QString sourceUri)
Chris@489 639 {
Chris@489 640 QString err;
Chris@489 641
Chris@490 642 QMutexLocker locker(&m_mutex);
Chris@489 643
Chris@489 644 if (!m_redland) {
Chris@489 645 m_redland = new WredlandWorldWrapper();
Chris@489 646 if (!m_redland->isOK()) {
Chris@489 647 cerr << "ERROR: SimpleSPARQLQuery::addSourceToModel: Failed to initialise Redland datastore" << endl;
Chris@489 648 delete m_redland;
Chris@489 649 m_redland = 0;
Chris@489 650 return false;
Chris@489 651 }
Chris@489 652 }
Chris@489 653
Chris@489 654 librdf_uri *uri = m_redland->getUri(sourceUri, err);
Chris@489 655
Chris@489 656 if (!uri) {
Chris@489 657 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to add source URI \"" << sourceUri.toStdString() << ": " << err.toStdString() << std::endl;
Chris@489 658 return false;
Chris@489 659 }
Chris@489 660 return true;
Chris@480 661 }
Chris@480 662
Chris@440 663 SimpleSPARQLQuery::Value
Chris@489 664 SimpleSPARQLQuery::singleResultQuery(QueryType type,
Chris@480 665 QString query, QString binding)
Chris@440 666 {
Chris@489 667 SimpleSPARQLQuery q(type, query);
Chris@440 668 ResultList results = q.execute();
Chris@440 669 if (!q.isOK()) {
Chris@440 670 cerr << "SimpleSPARQLQuery::singleResultQuery: ERROR: "
Chris@440 671 << q.getErrorString().toStdString() << endl;
Chris@440 672 return Value();
Chris@440 673 }
Chris@440 674 if (results.empty()) {
Chris@440 675 return Value();
Chris@440 676 }
Chris@440 677 for (int i = 0; i < results.size(); ++i) {
Chris@440 678 if (results[i].find(binding) != results[i].end() &&
Chris@440 679 results[i][binding].type != NoValue) {
Chris@440 680 return results[i][binding];
Chris@440 681 }
Chris@440 682 }
Chris@440 683 return Value();
Chris@440 684 }
Chris@440 685
Chris@440 686
Chris@440 687