annotate rdf/SimpleSPARQLQuery.cpp @ 507:0944d13689b2

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