annotate rdf/SimpleSPARQLQuery.cpp @ 661:a4faa1840384

* If a FileSource URL won't convert at all in strict mode, try again in tolerant mode (necessary for e.g. filenames with square brackets in them)
author Chris Cannam
date Tue, 19 Oct 2010 21:47:55 +0100
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