annotate rdf/SimpleSPARQLQuery.cpp @ 663:badbbf0921fa

Merge
author Chris Cannam
date Mon, 25 Oct 2010 11:09:02 +0200
parents 48f869ce8e64
children b4a8d8221eaf
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@644 26 // Rather than including <redland.h> -- for some reason redland.h
Chris@644 27 // includes <rasqal.h>, while the rasqal header actually gets
Chris@644 28 // installed as <rasqal/rasqal.h> which breaks the inclusion all over
Chris@644 29 // the place unless a very clever include path is set
Chris@644 30 #include <raptor.h>
Chris@644 31 #include <rasqal/rasqal.h>
Chris@644 32 #include <librdf.h>
Chris@480 33
Chris@492 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@480 41 class WredlandWorldWrapper
Chris@480 42 {
Chris@480 43 public:
Chris@492 44 WredlandWorldWrapper();
Chris@492 45 ~WredlandWorldWrapper();
Chris@480 46
Chris@492 47 bool isOK() const;
Chris@480 48
Chris@492 49 bool loadUriIntoDefaultModel(QString uriString, QString &errorString);
Chris@480 50
Chris@480 51 librdf_world *getWorld() { return m_world; }
Chris@480 52 const librdf_world *getWorld() const { return m_world; }
Chris@480 53
Chris@492 54 librdf_model *getDefaultModel() { return m_defaultModel; }
Chris@492 55 const librdf_model *getDefaultModel() const { return m_defaultModel; }
Chris@492 56
Chris@492 57 librdf_model *getModel(QString fromUri);
Chris@492 58 void freeModel(QString forUri);
Chris@480 59
Chris@480 60 private:
Chris@492 61 QMutex m_mutex;
Chris@492 62
Chris@480 63 librdf_world *m_world;
Chris@492 64 librdf_storage *m_defaultStorage;
Chris@492 65 librdf_model *m_defaultModel;
Chris@480 66
Chris@492 67 std::set<QString> m_defaultModelUris;
Chris@492 68
Chris@492 69 std::map<QString, librdf_storage *> m_ownStorageUris;
Chris@492 70 std::map<QString, librdf_model *> m_ownModelUris;
Chris@492 71
Chris@492 72 bool loadUri(librdf_model *model, QString uri, QString &errorString);
Chris@480 73 };
Chris@480 74
Chris@492 75 WredlandWorldWrapper::WredlandWorldWrapper() :
Chris@492 76 m_world(0), m_defaultStorage(0), m_defaultModel(0)
Chris@492 77 {
Chris@492 78 m_world = librdf_new_world();
Chris@492 79 if (!m_world) {
Chris@492 80 cerr << "SimpleSPARQLQuery: ERROR: Failed to create LIBRDF world!" << endl;
Chris@492 81 return;
Chris@492 82 }
Chris@492 83 librdf_world_open(m_world);
Chris@492 84
Chris@492 85 m_defaultStorage = librdf_new_storage(m_world, "trees", NULL, NULL);
Chris@492 86 if (!m_defaultStorage) {
Chris@495 87 std::cerr << "SimpleSPARQLQuery: WARNING: Failed to initialise Redland trees datastore, falling back to memory store" << std::endl;
Chris@492 88 m_defaultStorage = librdf_new_storage(m_world, NULL, NULL, NULL);
Chris@492 89 if (!m_defaultStorage) {
Chris@492 90 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland memory datastore" << std::endl;
Chris@492 91 return;
Chris@492 92 }
Chris@492 93 }
Chris@492 94 m_defaultModel = librdf_new_model(m_world, m_defaultStorage, NULL);
Chris@492 95 if (!m_defaultModel) {
Chris@492 96 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland data model" << std::endl;
Chris@492 97 return;
Chris@492 98 }
Chris@492 99 }
Chris@492 100
Chris@492 101 WredlandWorldWrapper::~WredlandWorldWrapper()
Chris@492 102 {
Chris@505 103 /*!!! This is a static singleton; destroying it while there are
Chris@505 104 queries outstanding can be problematic, it appears, and since
Chris@505 105 the storage is non-persistent there shouldn't be any need to
Chris@505 106 destroy it explicitly, except for the sake of tidiness.
Chris@505 107
Chris@492 108 while (!m_ownModelUris.empty()) {
Chris@492 109 librdf_free_model(m_ownModelUris.begin()->second);
Chris@492 110 m_ownModelUris.erase(m_ownModelUris.begin());
Chris@492 111 }
Chris@492 112 while (!m_ownStorageUris.empty()) {
Chris@492 113 librdf_free_storage(m_ownStorageUris.begin()->second);
Chris@492 114 m_ownStorageUris.erase(m_ownStorageUris.begin());
Chris@492 115 }
Chris@492 116 if (m_defaultModel) librdf_free_model(m_defaultModel);
Chris@492 117 if (m_defaultStorage) librdf_free_storage(m_defaultStorage);
Chris@492 118 if (m_world) librdf_free_world(m_world);
Chris@505 119 */
Chris@492 120 }
Chris@492 121
Chris@492 122 bool
Chris@492 123 WredlandWorldWrapper::isOK() const {
Chris@492 124 return (m_defaultModel != 0);
Chris@492 125 }
Chris@492 126
Chris@492 127 bool
Chris@492 128 WredlandWorldWrapper::loadUriIntoDefaultModel(QString uriString, QString &errorString)
Chris@492 129 {
Chris@492 130 QMutexLocker locker(&m_mutex);
Chris@492 131
Chris@492 132 if (m_defaultModelUris.find(uriString) != m_defaultModelUris.end()) {
Chris@492 133 return true;
Chris@492 134 }
Chris@492 135
Chris@492 136 if (loadUri(m_defaultModel, uriString, errorString)) {
Chris@492 137 m_defaultModelUris.insert(uriString);
Chris@492 138 return true;
Chris@492 139 } else {
Chris@492 140 return false;
Chris@492 141 }
Chris@492 142 }
Chris@492 143
Chris@492 144 librdf_model *
Chris@492 145 WredlandWorldWrapper::getModel(QString fromUri)
Chris@492 146 {
Chris@492 147 QMutexLocker locker(&m_mutex);
Chris@492 148 if (fromUri == "") {
Chris@492 149 return getDefaultModel();
Chris@492 150 }
Chris@492 151 if (m_ownModelUris.find(fromUri) != m_ownModelUris.end()) {
Chris@492 152 return m_ownModelUris[fromUri];
Chris@492 153 }
Chris@492 154 librdf_storage *storage = librdf_new_storage(m_world, "trees", NULL, NULL);
Chris@492 155 if (!storage) { // don't warn here, we probably already did it in main ctor
Chris@492 156 storage = librdf_new_storage(m_world, NULL, NULL, NULL);
Chris@492 157 }
Chris@492 158 librdf_model *model = librdf_new_model(m_world, storage, NULL);
Chris@492 159 if (!model) {
Chris@492 160 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to create new model" << std::endl;
Chris@492 161 librdf_free_storage(storage);
Chris@492 162 return 0;
Chris@492 163 }
Chris@492 164 QString err;
Chris@492 165 if (!loadUri(model, fromUri, err)) {
Chris@492 166 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to parse into new model: " << err.toStdString() << std::endl;
Chris@492 167 librdf_free_model(model);
Chris@492 168 librdf_free_storage(storage);
Chris@492 169 m_ownModelUris[fromUri] = 0;
Chris@492 170 return 0;
Chris@492 171 }
Chris@492 172 m_ownModelUris[fromUri] = model;
Chris@492 173 m_ownStorageUris[fromUri] = storage;
Chris@492 174 return model;
Chris@492 175 }
Chris@492 176
Chris@492 177 void
Chris@492 178 WredlandWorldWrapper::freeModel(QString forUri)
Chris@492 179 {
Chris@493 180 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@493 181 std::cerr << "SimpleSPARQLQuery::freeModel: Model uri = \"" << forUri.toStdString() << "\"" << std::endl;
Chris@493 182 #endif
Chris@493 183
Chris@492 184 QMutexLocker locker(&m_mutex);
Chris@492 185 if (forUri == "") {
Chris@492 186 std::cerr << "SimpleSPARQLQuery::freeModel: ERROR: Can't free default model" << std::endl;
Chris@492 187 return;
Chris@492 188 }
Chris@492 189 if (m_ownModelUris.find(forUri) == m_ownModelUris.end()) {
Chris@493 190 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@493 191 std::cerr << "SimpleSPARQLQuery::freeModel: NOTE: Unknown or already-freed model (uri = \"" << forUri.toStdString() << "\")" << std::endl;
Chris@493 192 #endif
Chris@492 193 return;
Chris@492 194 }
Chris@492 195
Chris@492 196 librdf_model *model = m_ownModelUris[forUri];
Chris@492 197 if (model) librdf_free_model(model);
Chris@492 198 m_ownModelUris.erase(forUri);
Chris@492 199
Chris@492 200 if (m_ownStorageUris.find(forUri) != m_ownStorageUris.end()) {
Chris@492 201 librdf_storage *storage = m_ownStorageUris[forUri];
Chris@492 202 if (storage) librdf_free_storage(storage);
Chris@492 203 m_ownStorageUris.erase(forUri);
Chris@492 204 }
Chris@492 205 }
Chris@492 206
Chris@492 207 bool
Chris@492 208 WredlandWorldWrapper::loadUri(librdf_model *model, QString uri, QString &errorString)
Chris@492 209 {
Chris@492 210 librdf_uri *luri = librdf_new_uri
Chris@492 211 (m_world, (const unsigned char *)uri.toUtf8().data());
Chris@492 212 if (!luri) {
Chris@492 213 errorString = "Failed to construct librdf_uri!";
Chris@492 214 return false;
Chris@492 215 }
Chris@492 216
Chris@492 217 librdf_parser *parser = librdf_new_parser(m_world, "guess", NULL, NULL);
Chris@492 218 if (!parser) {
Chris@492 219 errorString = "Failed to initialise Redland parser";
Chris@492 220 return false;
Chris@492 221 }
Chris@507 222
Chris@507 223 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 224 std::cerr << "About to parse \"" << uri.toStdString() << "\"" << std::endl;
Chris@507 225 #endif
Chris@492 226
Chris@492 227 Profiler p("SimpleSPARQLQuery: Parse URI into LIBRDF model");
Chris@492 228
Chris@492 229 if (librdf_parser_parse_into_model(parser, luri, NULL, model)) {
Chris@492 230
Chris@492 231 errorString = QString("Failed to parse RDF from URI \"%1\"")
Chris@492 232 .arg(uri);
Chris@492 233 librdf_free_parser(parser);
Chris@492 234 return false;
Chris@492 235
Chris@492 236 } else {
Chris@492 237
Chris@492 238 librdf_free_parser(parser);
Chris@492 239 return true;
Chris@492 240 }
Chris@492 241 }
Chris@492 242
Chris@492 243
Chris@439 244 class SimpleSPARQLQuery::Impl
Chris@439 245 {
Chris@439 246 public:
Chris@489 247 Impl(SimpleSPARQLQuery::QueryType, QString query);
Chris@439 248 ~Impl();
Chris@439 249
Chris@489 250 static bool addSourceToModel(QString sourceUri);
Chris@492 251 static void closeSingleSource(QString sourceUri);
Chris@489 252
Chris@439 253 void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; }
Chris@439 254 bool wasCancelled() const { return m_cancelled; }
Chris@439 255
Chris@439 256 ResultList execute();
Chris@439 257
Chris@439 258 bool isOK() const;
Chris@439 259 QString getErrorString() const;
Chris@439 260
Chris@439 261 protected:
Chris@480 262 static QMutex m_mutex;
Chris@480 263
Chris@526 264 static WredlandWorldWrapper *m_redland;
Chris@480 265
Chris@480 266 ResultList executeDirectParser();
Chris@480 267 ResultList executeDatastore();
Chris@492 268 ResultList executeFor(QString modelUri);
Chris@480 269
Chris@489 270 QueryType m_type;
Chris@439 271 QString m_query;
Chris@439 272 QString m_errorString;
Chris@439 273 ProgressReporter *m_reporter;
Chris@439 274 bool m_cancelled;
Chris@439 275 };
Chris@439 276
Chris@526 277 WredlandWorldWrapper *SimpleSPARQLQuery::Impl::m_redland = 0;
Chris@480 278
Chris@480 279 QMutex SimpleSPARQLQuery::Impl::m_mutex;
Chris@480 280
Chris@489 281 SimpleSPARQLQuery::SimpleSPARQLQuery(QueryType type, QString query) :
Chris@489 282 m_impl(new Impl(type, query))
Chris@480 283 {
Chris@480 284 }
Chris@439 285
Chris@439 286 SimpleSPARQLQuery::~SimpleSPARQLQuery()
Chris@439 287 {
Chris@439 288 delete m_impl;
Chris@439 289 }
Chris@439 290
Chris@439 291 void
Chris@439 292 SimpleSPARQLQuery::setProgressReporter(ProgressReporter *reporter)
Chris@439 293 {
Chris@439 294 m_impl->setProgressReporter(reporter);
Chris@439 295 }
Chris@439 296
Chris@439 297 bool
Chris@439 298 SimpleSPARQLQuery::wasCancelled() const
Chris@439 299 {
Chris@439 300 return m_impl->wasCancelled();
Chris@439 301 }
Chris@439 302
Chris@439 303 SimpleSPARQLQuery::ResultList
Chris@439 304 SimpleSPARQLQuery::execute()
Chris@439 305 {
Chris@439 306 return m_impl->execute();
Chris@439 307 }
Chris@439 308
Chris@439 309 bool
Chris@439 310 SimpleSPARQLQuery::isOK() const
Chris@439 311 {
Chris@439 312 return m_impl->isOK();
Chris@439 313 }
Chris@439 314
Chris@439 315 QString
Chris@439 316 SimpleSPARQLQuery::getErrorString() const
Chris@439 317 {
Chris@439 318 return m_impl->getErrorString();
Chris@439 319 }
Chris@439 320
Chris@489 321 bool
Chris@489 322 SimpleSPARQLQuery::addSourceToModel(QString sourceUri)
Chris@480 323 {
Chris@489 324 return SimpleSPARQLQuery::Impl::addSourceToModel(sourceUri);
Chris@480 325 }
Chris@480 326
Chris@492 327 void
Chris@492 328 SimpleSPARQLQuery::closeSingleSource(QString sourceUri)
Chris@492 329 {
Chris@492 330 SimpleSPARQLQuery::Impl::closeSingleSource(sourceUri);
Chris@492 331 }
Chris@492 332
Chris@489 333 SimpleSPARQLQuery::Impl::Impl(QueryType type, QString query) :
Chris@489 334 m_type(type),
Chris@439 335 m_query(query),
Chris@439 336 m_reporter(0),
Chris@439 337 m_cancelled(false)
Chris@439 338 {
Chris@439 339 }
Chris@439 340
Chris@439 341 SimpleSPARQLQuery::Impl::~Impl()
Chris@439 342 {
Chris@439 343 }
Chris@439 344
Chris@439 345 bool
Chris@439 346 SimpleSPARQLQuery::Impl::isOK() const
Chris@439 347 {
Chris@439 348 return (m_errorString == "");
Chris@439 349 }
Chris@439 350
Chris@439 351 QString
Chris@439 352 SimpleSPARQLQuery::Impl::getErrorString() const
Chris@439 353 {
Chris@439 354 return m_errorString;
Chris@439 355 }
Chris@439 356
Chris@439 357 SimpleSPARQLQuery::ResultList
Chris@439 358 SimpleSPARQLQuery::Impl::execute()
Chris@439 359 {
Chris@439 360 ResultList list;
Chris@439 361
Chris@490 362 QMutexLocker locker(&m_mutex);
Chris@480 363
Chris@526 364 if (!m_redland) {
Chris@526 365 m_redland = new WredlandWorldWrapper();
Chris@526 366 }
Chris@526 367
Chris@526 368 if (!m_redland->isOK()) {
Chris@492 369 cerr << "ERROR: SimpleSPARQLQuery::execute: Failed to initialise Redland datastore" << endl;
Chris@492 370 return list;
Chris@440 371 }
Chris@480 372
Chris@489 373 if (m_type == QueryFromSingleSource) {
Chris@480 374 return executeDirectParser();
Chris@480 375 } else {
Chris@480 376 return executeDatastore();
Chris@480 377 }
Chris@492 378
Chris@492 379 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 380 if (m_errorString != "") {
Chris@492 381 std::cerr << "SimpleSPARQLQuery::execute: error returned: \""
Chris@492 382 << m_errorString.toStdString() << "\"" << std::endl;
Chris@492 383 }
Chris@492 384 #endif
Chris@480 385 }
Chris@480 386
Chris@480 387 SimpleSPARQLQuery::ResultList
Chris@480 388 SimpleSPARQLQuery::Impl::executeDirectParser()
Chris@480 389 {
Chris@492 390 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 391 std::cerr << "SimpleSPARQLQuery::executeDirectParser: Query is: \"" << m_query.toStdString() << "\"" << std::endl;
Chris@492 392 #endif
Chris@492 393
Chris@480 394 ResultList list;
Chris@480 395
Chris@480 396 Profiler profiler("SimpleSPARQLQuery::executeDirectParser");
Chris@480 397
Chris@492 398 static QRegExp fromRE("from\\s+<([^>]+)>", Qt::CaseInsensitive);
Chris@492 399 QString fromUri;
Chris@492 400
Chris@492 401 if (fromRE.indexIn(m_query) < 0) {
Chris@492 402 std::cerr << "SimpleSPARQLQuery::executeDirectParser: Query contains no FROM clause, nothing to parse from" << std::endl;
Chris@492 403 return list;
Chris@492 404 } else {
Chris@492 405 fromUri = fromRE.cap(1);
Chris@492 406 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 407 std::cerr << "SimpleSPARQLQuery::executeDirectParser: FROM URI is <"
Chris@492 408 << fromUri.toStdString() << ">" << std::endl;
Chris@440 409 #endif
Chris@439 410 }
Chris@439 411
Chris@492 412 return executeFor(fromUri);
Chris@439 413 }
Chris@440 414
Chris@480 415 SimpleSPARQLQuery::ResultList
Chris@480 416 SimpleSPARQLQuery::Impl::executeDatastore()
Chris@480 417 {
Chris@492 418 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 419 std::cerr << "SimpleSPARQLQuery::executeDatastore: Query is: \"" << m_query.toStdString() << "\"" << std::endl;
Chris@492 420 #endif
Chris@492 421
Chris@480 422 ResultList list;
Chris@489 423
Chris@480 424 Profiler profiler("SimpleSPARQLQuery::executeDatastore");
Chris@480 425
Chris@492 426 return executeFor("");
Chris@492 427 }
Chris@492 428
Chris@492 429 SimpleSPARQLQuery::ResultList
Chris@492 430 SimpleSPARQLQuery::Impl::executeFor(QString modelUri)
Chris@492 431 {
Chris@492 432 ResultList list;
Chris@492 433 librdf_query *query;
Chris@492 434
Chris@493 435 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@480 436 static std::map<QString, int> counter;
Chris@480 437 if (counter.find(m_query) == counter.end()) counter[m_query] = 1;
Chris@480 438 else ++counter[m_query];
Chris@480 439 std::cerr << "Counter for this query: " << counter[m_query] << std::endl;
Chris@492 440 std::cerr << "Base URI is: \"" << modelUri.toStdString() << "\"" << std::endl;
Chris@493 441 #endif
Chris@480 442
Chris@480 443 {
Chris@480 444 Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query");
Chris@480 445 query = librdf_new_query
Chris@526 446 (m_redland->getWorld(), "sparql", NULL,
Chris@489 447 (const unsigned char *)m_query.toUtf8().data(), NULL);
Chris@480 448 }
Chris@480 449
Chris@480 450 if (!query) {
Chris@480 451 m_errorString = "Failed to construct query";
Chris@480 452 return list;
Chris@480 453 }
Chris@480 454
Chris@480 455 librdf_query_results *results;
Chris@480 456 {
Chris@480 457 Profiler p("SimpleSPARQLQuery: Execute LIBRDF query");
Chris@526 458 results = librdf_query_execute(query, m_redland->getModel(modelUri));
Chris@480 459 }
Chris@480 460
Chris@480 461 if (!results) {
Chris@511 462 m_errorString = "RDF query failed";
Chris@480 463 librdf_free_query(query);
Chris@480 464 return list;
Chris@480 465 }
Chris@480 466
Chris@480 467 if (!librdf_query_results_is_bindings(results)) {
Chris@511 468 m_errorString = "RDF query returned non-bindings results";
Chris@480 469 librdf_free_query_results(results);
Chris@480 470 librdf_free_query(query);
Chris@480 471 return list;
Chris@480 472 }
Chris@480 473
Chris@480 474 int resultCount = 0;
Chris@480 475 int resultTotal = librdf_query_results_get_count(results); // probably wrong
Chris@480 476 m_cancelled = false;
Chris@480 477
Chris@480 478 while (!librdf_query_results_finished(results)) {
Chris@480 479
Chris@480 480 int count = librdf_query_results_get_bindings_count(results);
Chris@480 481
Chris@480 482 KeyValueMap resultmap;
Chris@480 483
Chris@480 484 for (int i = 0; i < count; ++i) {
Chris@480 485
Chris@480 486 const char *name =
Chris@480 487 librdf_query_results_get_binding_name(results, i);
Chris@480 488
Chris@490 489 if (!name) {
Chris@490 490 std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl;
Chris@490 491 continue;
Chris@490 492 }
Chris@490 493
Chris@480 494 librdf_node *node =
Chris@480 495 librdf_query_results_get_binding_value(results, i);
Chris@480 496
Chris@480 497 QString key = (const char *)name;
Chris@480 498
Chris@480 499 if (!node) {
Chris@492 500 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 501 std::cerr << i << ". " << key.toStdString() << " -> (nil)" << std::endl;
Chris@492 502 #endif
Chris@480 503 resultmap[key] = Value();
Chris@480 504 continue;
Chris@480 505 }
Chris@480 506
Chris@480 507 ValueType type = LiteralValue;
Chris@481 508 QString text;
Chris@481 509
Chris@481 510 if (librdf_node_is_resource(node)) {
Chris@481 511
Chris@481 512 type = URIValue;
Chris@481 513 librdf_uri *uri = librdf_node_get_uri(node);
Chris@490 514 const char *us = (const char *)librdf_uri_as_string(uri);
Chris@490 515
Chris@490 516 if (!us) {
Chris@490 517 std::cerr << "WARNING: Result " << i << " of query claims URI type, but has null URI" << std::endl;
Chris@490 518 } else {
Chris@490 519 text = us;
Chris@490 520 }
Chris@481 521
Chris@481 522 } else if (librdf_node_is_literal(node)) {
Chris@481 523
Chris@481 524 type = LiteralValue;
Chris@490 525
Chris@490 526 const char *lit = (const char *)librdf_node_get_literal_value(node);
Chris@490 527 if (!lit) {
Chris@490 528 std::cerr << "WARNING: Result " << i << " of query claims literal type, but has no literal" << std::endl;
Chris@490 529 } else {
Chris@490 530 text = lit;
Chris@490 531 }
Chris@481 532
Chris@481 533 } else if (librdf_node_is_blank(node)) {
Chris@481 534
Chris@481 535 type = BlankValue;
Chris@481 536
Chris@494 537 const char *lit = (const char *)librdf_node_get_literal_value(node);
Chris@494 538 if (lit) text = lit;
Chris@494 539
Chris@481 540 } else {
Chris@481 541
Chris@480 542 cerr << "SimpleSPARQLQuery: LIBRDF query returned unknown node type (not resource, literal, or blank)" << endl;
Chris@480 543 }
Chris@480 544
Chris@480 545 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@481 546 cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << endl;
Chris@480 547 #endif
Chris@480 548
Chris@480 549 resultmap[key] = Value(type, text);
Chris@480 550
Chris@492 551 // librdf_free_node(node);
Chris@480 552 }
Chris@480 553
Chris@480 554 list.push_back(resultmap);
Chris@480 555
Chris@480 556 librdf_query_results_next(results);
Chris@480 557
Chris@480 558 resultCount++;
Chris@480 559
Chris@480 560 if (m_reporter) {
Chris@480 561 if (resultCount >= resultTotal) {
Chris@480 562 if (m_reporter->isDefinite()) m_reporter->setDefinite(false);
Chris@480 563 m_reporter->setProgress(resultCount);
Chris@480 564 } else {
Chris@480 565 m_reporter->setProgress((resultCount * 100) / resultTotal);
Chris@480 566 }
Chris@480 567
Chris@480 568 if (m_reporter->wasCancelled()) {
Chris@480 569 m_cancelled = true;
Chris@480 570 break;
Chris@480 571 }
Chris@480 572 }
Chris@480 573 }
Chris@480 574
Chris@480 575 librdf_free_query_results(results);
Chris@480 576 librdf_free_query(query);
Chris@480 577
Chris@481 578 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 579 cerr << "SimpleSPARQLQuery::executeDatastore: All results retrieved (" << resultCount << " of them)" << endl;
Chris@481 580 #endif
Chris@480 581
Chris@480 582 return list;
Chris@489 583 }
Chris@489 584
Chris@489 585 bool
Chris@489 586 SimpleSPARQLQuery::Impl::addSourceToModel(QString sourceUri)
Chris@489 587 {
Chris@489 588 QString err;
Chris@489 589
Chris@490 590 QMutexLocker locker(&m_mutex);
Chris@489 591
Chris@527 592 if (!m_redland) {
Chris@527 593 m_redland = new WredlandWorldWrapper();
Chris@527 594 }
Chris@527 595
Chris@526 596 if (!m_redland->isOK()) {
Chris@492 597 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to initialise Redland datastore" << std::endl;
Chris@492 598 return false;
Chris@489 599 }
Chris@489 600
Chris@526 601 if (!m_redland->loadUriIntoDefaultModel(sourceUri, err)) {
Chris@489 602 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to add source URI \"" << sourceUri.toStdString() << ": " << err.toStdString() << std::endl;
Chris@489 603 return false;
Chris@489 604 }
Chris@489 605 return true;
Chris@480 606 }
Chris@480 607
Chris@492 608 void
Chris@492 609 SimpleSPARQLQuery::Impl::closeSingleSource(QString sourceUri)
Chris@492 610 {
Chris@492 611 QMutexLocker locker(&m_mutex);
Chris@492 612
Chris@526 613 m_redland->freeModel(sourceUri);
Chris@492 614 }
Chris@492 615
Chris@440 616 SimpleSPARQLQuery::Value
Chris@489 617 SimpleSPARQLQuery::singleResultQuery(QueryType type,
Chris@480 618 QString query, QString binding)
Chris@440 619 {
Chris@489 620 SimpleSPARQLQuery q(type, query);
Chris@440 621 ResultList results = q.execute();
Chris@440 622 if (!q.isOK()) {
Chris@440 623 cerr << "SimpleSPARQLQuery::singleResultQuery: ERROR: "
Chris@440 624 << q.getErrorString().toStdString() << endl;
Chris@440 625 return Value();
Chris@440 626 }
Chris@440 627 if (results.empty()) {
Chris@440 628 return Value();
Chris@440 629 }
Chris@440 630 for (int i = 0; i < results.size(); ++i) {
Chris@440 631 if (results[i].find(binding) != results[i].end() &&
Chris@440 632 results[i][binding].type != NoValue) {
Chris@440 633 return results[i][binding];
Chris@440 634 }
Chris@440 635 }
Chris@440 636 return Value();
Chris@440 637 }
Chris@440 638
Chris@440 639
Chris@440 640