525
525
const QStringList uriHashN3 = resourceHashToN3(uriHash);
526
526
if(!uriHashN3.isEmpty()) {
527
const QSet<Soprano::Node> existingValues = QSet<Soprano::Node>::fromList(resolvedNodes.values());
527
QHash<QUrl, QList<Soprano::Node> > valuesToRemove;
528
const QSet<Soprano::Node> setValues = QSet<Soprano::Node>::fromList(resolvedNodes.values());
528
529
QSet<QUrl> graphs;
529
530
QList<Soprano::BindingSet> existing
530
531
= executeQuery(QString::fromLatin1("select ?r ?v ?g where { graph ?g { ?r %1 ?v . FILTER(?r in (%2)) . } . }")
532
533
uriHashN3.join(QLatin1String(","))),
533
534
Soprano::Query::QueryLanguageSparql).allBindings();
534
535
Q_FOREACH(const Soprano::BindingSet& binding, existing) {
535
if(!existingValues.contains(binding["v"])) {
536
if(!setValues.contains(binding["v"])) {
536
537
removeAllStatements(binding["r"], property, binding["v"]);
537
538
graphs.insert(binding["g"].uri());
538
d->m_watchManager->removeProperty(binding["r"], property, binding["v"]);
539
valuesToRemove[binding["r"].uri()].append(binding["v"]);
541
542
removeTrailingGraphs(graphs);
546
// And finally add the rest of the statements (only if there is anything to add)
548
if(!nodes.isEmpty()) {
549
addProperty(uriHash, property, resolvedNodes, app);
544
// construct the lists of old and new values
545
QHash<QUrl, QList<Soprano::Node> > addedValues;
548
// And finally add the rest of the statements (only if there is anything to add)
550
if(!nodes.isEmpty()) {
551
addedValues = addProperty(uriHash, property, resolvedNodes, app);
555
// Inform interested parties about the changes
557
QSet<QUrl> allChangedResources = uriHash.values().toSet();
558
allChangedResources.remove(QUrl());
559
foreach(const QUrl& res, allChangedResources) {
560
const QList<Soprano::Node> added = addedValues.value(res);
561
const QList<Soprano::Node> removed = valuesToRemove.value(res);
562
if(!added.isEmpty() || !removed.isEmpty()) {
563
d->m_watchManager->changeProperty(res,
628
647
QSet<QUrl> graphs;
629
const QString propertyN3 = Soprano::Node::resourceToN3(property);
630
648
foreach( const QUrl & res, resolvedResources ) {
631
649
const QList<Soprano::BindingSet> valueGraphs
632
650
= executeQuery(QString::fromLatin1("select ?g ?v where { graph ?g { %1 %2 ?v . } . FILTER(?v in (%3)) . }")
633
651
.arg(Soprano::Node::resourceToN3(res),
652
Soprano::Node::resourceToN3(property),
635
653
nodesToN3(resolvedNodes).join(QLatin1String(","))),
636
654
Soprano::Query::QueryLanguageSparql).allBindings();
656
QSet<Soprano::Node> removedValues;
638
657
foreach(const Soprano::BindingSet& binding, valueGraphs) {
658
const Soprano::Node v = binding["v"];
639
659
graphs.insert( binding["g"].uri() );
640
removeAllStatements( res, property, binding["v"] );
641
d->m_watchManager->removeProperty( res, property, binding["v"]);
660
removeAllStatements( res, property, v );
664
if(!removedValues.isEmpty()) {
665
d->m_watchManager->changeProperty( res, property, QList<Soprano::Node>(), removedValues.toList() );
644
668
// we only update the mtime in case we actually remove anything
727
751
QSet<QUrl> graphs;
728
752
foreach( const QUrl & res, resolvedResources ) {
729
753
QSet<Soprano::Node> propertiesToRemove;
730
QList<QPair<Soprano::Node, Soprano::Node> > propertyValues;
754
QMultiHash<QUrl, Soprano::Node> propertyValues;
731
755
Soprano::QueryResultIterator it
732
756
= executeQuery(QString::fromLatin1("select distinct ?g ?p ?v where { graph ?g { %1 ?p ?v . } . FILTER(?p in (%2)) . }")
733
757
.arg(Soprano::Node::resourceToN3(res),
747
771
// inform interested parties
748
for(QList<QPair<Soprano::Node, Soprano::Node> >::const_iterator it = propertyValues.constBegin();
749
it != propertyValues.constEnd(); ++it) {
750
d->m_watchManager->removeProperty(res, it->first.uri(), it->second);
772
for(QMultiHash<QUrl, Soprano::Node>::const_iterator it = propertyValues.constBegin();
773
it != propertyValues.constEnd(); ) {
774
QList<Soprano::Node> values;
775
values << it.value();
777
const QUrl property = it.key();
778
for( ++it; it != propertyValues.constEnd() && it.key() == property; ++it ) {
779
values << it.value();
782
d->m_watchManager->changeProperty(res, property, QList<Soprano::Node>(), values);
753
785
// we only update the mtime in case we actually remove anything
1508
1540
const Soprano::Error::Error error = d->m_classAndPropertyTree->lastError();
1510
setError( error.message(), error.code() );
1511
1543
return QHash<QUrl, QUrl>();
1513
1545
syncRes.insert( hit.key(), n );
1546
1578
else if(state == NonExistingFileUrl) {
1547
1579
setError(QString::fromLatin1("Cannot store information about non-existing local files. File '%1' does not exist.").arg(object.uri().toLocalFile()),
1548
Soprano::Error::ErrorInvalidArgument);
1580
Soprano::Error::ErrorInvalidArgument);
1549
1581
return QHash<QUrl, QUrl>();
1551
1583
else if(state == ExistingFileUrl || state==SupportedUrl) {
1581
1613
else if(state == OtherUri) {
1582
1614
// We use resolveUrl to check if the otherUri exists. If it doesn't exist,
1583
1615
// then resolveUrl which set the last error
1616
// trueg: seems like a waste to not use the resolved uri here!
1584
1617
const QUrl legacyUri = resolveUrl( object.uri() );
1585
1618
if( lastError() )
1586
1619
return QHash<QUrl, QUrl>();
1593
1626
QUrl url = object.uri();
1594
1627
if( url.scheme() == QLatin1String("file") && !QFile::exists(url.toLocalFile()) ) {
1595
1628
setError(QString::fromLatin1("Cannot store information about non-existing local files. File '%1' does not exist.").arg(object.uri().toLocalFile()),
1596
Soprano::Error::ErrorInvalidArgument);
1629
Soprano::Error::ErrorInvalidArgument);
1597
1630
return QHash<QUrl, QUrl>();
1600
1633
} // if object.isResurce
1601
1634
} // while( it.hasNext() )
1603
1635
// The resource is now ready.
1604
1636
syncResources << syncRes;
2327
2359
// TODO: emit resource watcher resource creation signals
2328
void Nepomuk::DataManagementModel::addProperty(const QHash<QUrl, QUrl> &resources, const QUrl &property, const QHash<Soprano::Node, Soprano::Node> &nodes, const QString &app)
2360
QHash<QUrl, QList<Soprano::Node> > Nepomuk::DataManagementModel::addProperty(const QHash<QUrl, QUrl> &resources, const QUrl &property, const QHash<Soprano::Node, Soprano::Node> &nodes, const QString &app, bool signalPropertyChanged)
2330
2362
kDebug() << resources << property << nodes << app;
2331
2363
Q_ASSERT(!resources.isEmpty());
2412
2444
if(!knownResources.isEmpty()) {
2413
2445
const QString existingValuesQuery = QString::fromLatin1("select distinct ?r ?v ?g ?m "
2414
"(select count(*) where { graph ?g { ?s ?p ?o . } . FILTER(%5) . }) as ?cnt "
2446
"(select count(*) where { graph ?g { ?s ?p ?o . } . FILTER(%4) . }) as ?cnt "
2416
2448
"graph ?g { ?r %2 ?v . } . "
2418
2450
"FILTER(?r in (%3)) . "
2419
"FILTER(?v in (%4)) . }")
2451
"FILTER(?v in (%5)) . }")
2420
2452
.arg(Soprano::Node::resourceToN3(NRL::coreGraphMetadataFor()),
2421
2453
Soprano::Node::resourceToN3(property),
2422
2454
resourcesToN3(knownResources).join(QLatin1String(",")),
2423
nodesToN3(resolvedNodes).join(QLatin1String(",")),
2424
createResourceMetadataPropertyFilter(QLatin1String("?p")));
2455
createResourceMetadataPropertyFilter(QLatin1String("?p")),
2456
nodesToN3(resolvedNodes).join(QLatin1String(",")));
2425
2457
QList<Soprano::BindingSet> existingValueBindings = executeQuery(existingValuesQuery, Soprano::Query::QueryLanguageSparql).allBindings();
2426
2458
Q_FOREACH(const Soprano::BindingSet& binding, existingValueBindings) {
2427
2459
kDebug() << "Existing value" << binding;
2431
2463
const QUrl m = binding["m"].uri();
2432
2464
const int cnt = binding["cnt"].literal().toInt();
2434
// we handle this property here - thus, no need to handle it below
2435
finalProperties.remove(qMakePair(r, v));
2437
// in case the app is the same there is no need to do anything
2438
if(containsStatement(g, NAO::maintainedBy(), appRes, m)) {
2442
// we can reuse the graph
2443
addStatement(g, NAO::maintainedBy(), appRes, m);
2446
// we need to split the graph
2447
// FIXME: do not split the same graph again and again. Check if the graph in question already is the one we created.
2448
const QUrl newGraph = splitGraph(g, m, appRes);
2450
// and finally move the actual property over to the new graph
2451
removeStatement(r, property, v, g);
2452
addStatement(r, property, v, newGraph);
2466
// in case we do not signal the changes we restrict the values already in the query
2467
if(resolvedNodes.contains(v)) {
2468
// we handle this property here - thus, no need to handle it below
2469
finalProperties.remove(qMakePair(r, v));
2471
// in case the app is the same there is no need to do anything
2472
if(containsStatement(g, NAO::maintainedBy(), appRes, m)) {
2476
// we can reuse the graph
2477
addStatement(g, NAO::maintainedBy(), appRes, m);
2480
// we need to split the graph
2481
// FIXME: do not split the same graph again and again. Check if the graph in question already is the one we created.
2482
const QUrl newGraph = splitGraph(g, m, appRes);
2484
// and finally move the actual property over to the new graph
2485
removeStatement(r, property, v, g);
2486
addStatement(r, property, v, newGraph);
2463
2498
graph = createGraph( app );
2464
2499
if(!graph.isValid()) {
2465
2500
// error has been set in createGraph
2501
return QHash<QUrl, QList<Soprano::Node> >();
2470
2505
// add all the data
2471
2506
// TODO: check if using one big sparql insert improves performance
2472
QSet<QUrl> finalResources;
2507
QHash<QUrl, QList<Soprano::Node> > finalValuesPerResource;
2473
2508
for(QSet<QPair<QUrl, Soprano::Node> >::const_iterator it = finalProperties.constBegin(); it != finalProperties.constEnd(); ++it) {
2474
2509
addStatement(it->first, property, it->second, graph);
2475
2510
if(property == NIE::url() && it->second.uri().scheme() == QLatin1String("file")) {
2476
2511
addStatement(it->first, RDF::type(), NFO::FileDataObject(), graph);
2478
finalResources.insert(it->first);
2479
d->m_watchManager->addProperty(it->first, property, it->second);
2513
finalValuesPerResource[it->first].append(it->second);
2516
// inform interested parties
2517
if(signalPropertyChanged) {
2518
for(QHash<QUrl, QList<Soprano::Node> >::const_iterator it = finalValuesPerResource.constBegin(); it != finalValuesPerResource.constEnd(); ++it) {
2519
d->m_watchManager->changeProperty(it.key(), property, it.value(), QList<Soprano::Node>());
2482
2523
// update modification date
2483
Q_FOREACH(const QUrl& res, finalResources) {
2524
Q_FOREACH(const QUrl& res, finalValuesPerResource.keys()) {
2484
2525
updateModificationDate(res, graph, QDateTime::currentDateTime(), true);
2528
return finalValuesPerResource;
2531
return QHash<QUrl, QList<Soprano::Node> >();
2489
2534
bool Nepomuk::DataManagementModel::doesResourceExist(const QUrl &res, const QUrl& graph) const
2580
2625
QHash<Soprano::Node, Soprano::Node> resolvedNodes;
2581
2626
Q_FOREACH(const Soprano::Node& node, nodes) {
2582
2627
if(node.isResource()) {
2583
resolvedNodes.insert(node, resolveUrl(node.uri(), true));
2628
const QUrl resolved = resolveUrl(node.uri(), true);
2629
if(resolved.isEmpty() && lastError()) {
2632
resolvedNodes.insert(node, resolved);
2586
2635
resolvedNodes.insert(node, node);