24 #include "resourcemanager_p.h"
35 #include <Soprano/Statement>
36 #include <Soprano/StatementIterator>
37 #include <Soprano/QueryResultIterator>
38 #include <Soprano/NodeIterator>
39 #include <Soprano/Model>
40 #include <Soprano/Vocabulary/RDFS>
41 #include <Soprano/Vocabulary/RDF>
42 #include <Soprano/Vocabulary/Xesam>
43 #include <Soprano/Vocabulary/NAO>
45 #include <QtCore/QFile>
46 #include <QtCore/QDateTime>
47 #include <QtCore/QMutexLocker>
48 #include <QtCore/QFileInfo>
52 #include <kcomponentdata.h>
54 #include <kdbusconnectionpool.h>
55 #include <QtDBus/QDBusMessage>
57 using namespace Soprano;
59 #define MAINMODEL (m_rm->m_manager->mainModel())
61 using namespace Soprano::Vocabulary;
62 using namespace Nepomuk2::Vocabulary;
66 m_type(type.isEmpty() ? RDFS::
Resource() : type),
67 m_dataMutex(QMutex::Recursive),
69 m_addedToWatcher(false),
70 m_watchEnabled(false),
73 if( !uri.isEmpty() ) {
76 QMutexLocker locker(&m_rm->mutex);
77 m_rm->m_initializedData.insert( uri,
this );
80 if( !kickOffUri.isEmpty() ) {
81 if( kickOffUri.scheme().isEmpty() ) {
82 m_naoIdentifier = kickOffUri.toString();
83 m_cache.insert( NAO::identifier(), m_naoIdentifier );
85 QMutexLocker locker(&m_rm->mutex);
86 m_rm->m_identifierKickOff.insert(m_naoIdentifier,
this);
89 m_nieUrl = kickOffUri;
90 if( m_nieUrl.isLocalFile() ) {
92 QFileInfo fileInfo(m_nieUrl.toLocalFile());
93 if( fileInfo.isSymLink() )
94 m_nieUrl = KUrl::fromLocalFile( fileInfo.canonicalFilePath() );
96 m_cache.insert( NIE::url(), m_nieUrl );
98 QMutexLocker locker(&m_rm->mutex);
99 m_rm->m_urlKickOff.insert(m_nieUrl,
this);
113 QMutexLocker lock(&m_dataMutex);
114 return( m_uri.scheme() == QLatin1String(
"file") ||
115 m_nieUrl.scheme() == QLatin1String(
"file") ||
116 hasProperty( RDF::type(), NFO::FileDataObject() ) );
123 QMutexLocker lock(&m_dataMutex);
130 QUrl mainType = RDFS::Resource();
135 QMutexLocker lock(&m_dataMutex);
136 QList<QUrl> types = m_cache.value(RDF::type()).toUrlList();
137 foreach(
const QUrl& t, types) {
142 if ( storedTypeClass.
isSubClassOf( currentTypeClass ) ) {
143 mainType = storedTypeClass.
uri();
149 Types::Class nieInformationElementClass( NIE::InformationElement() );
151 if( ( currentTypeClass == nieDataObjectClass ||
152 currentTypeClass.
isSubClassOf( nieDataObjectClass ) ) &&
153 ( storedTypeClass == nieInformationElementClass ||
154 storedTypeClass.
isSubClassOf( nieInformationElementClass ) ) ) {
155 mainType = storedTypeClass.
uri();
166 QMutexLocker rmMutexLocker(&m_rm->mutex);
167 QMutexLocker locker(&m_dataMutex);
175 const QString nao = m_cache.value(NAO::identifier()).toString();
176 m_rm->m_identifierKickOff.remove( nao );
177 const QUrl nieUrl = m_cache.value(NIE::url()).toUrl();
178 m_rm->m_urlKickOff.remove( nieUrl );
180 if( !m_uri.isEmpty() ) {
181 m_rm->m_initializedData.remove( m_uri );
188 m_naoIdentifier.clear();
190 m_cacheDirty =
false;
191 m_type = RDFS::Resource();
200 QMutexLocker lock(&m_dataMutex);
211 QMutexLocker lock(&m_dataMutex);
213 if( it == m_cache.constEnd() )
225 QMutexLocker lock(&m_dataMutex);
227 if( it == m_cache.constEnd() )
230 QList<Variant> thisVals = it.value().toVariantList();
232 Q_FOREACH(
const Variant& val, vals ) {
233 if( !thisVals.contains(val) )
247 QMutexLocker lock(&m_dataMutex);
250 if ( it == m_cache.constEnd() ) {
261 QMutexLocker lock(&m_dataMutex);
263 if ( m_uri.isEmpty() ) {
265 if ( m_nieUrl.isValid() && m_nieUrl.isLocalFile() ) {
266 types << NFO::FileDataObject();
267 if( QFileInfo(m_nieUrl.toLocalFile()).isDir() )
268 types << NFO::Folder();
272 QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String(
"org.kde.NepomukStorage"),
273 QLatin1String(
"/datamanagement"),
274 QLatin1String(
"org.kde.nepomuk.DataManagement"),
275 QLatin1String(
"createResource") );
277 msg.setArguments( QVariantList()
279 << QString() << QString()
280 << KGlobal::mainComponent().componentName() );
282 QDBusConnection bus = KDBusConnectionPool::threadConnection();
283 QDBusMessage reply = bus.call( msg );
284 if( reply.type() == QDBusMessage::ErrorMessage ) {
286 kWarning() << reply.errorMessage();
290 m_uri = reply.arguments().at(0).toUrl();
292 QList<Soprano::Node> nodes =
MAINMODEL->listStatements( m_uri, RDF::type(), QUrl() )
293 .iterateObjects().allNodes();
295 foreach(
const Soprano::Node& node, nodes)
297 m_cache.insert(RDF::type(), types);
299 if( !m_naoIdentifier.isEmpty() ) {
302 m_naoIdentifier.clear();
304 if( !m_nieUrl.isEmpty() ) {
311 QMutexLocker rmlock(&m_rm->mutex);
314 m_rm->m_initializedData.insert( m_uri,
this );
322 void Nepomuk2::ResourceData::addToWatcher()
324 if( m_watchEnabled && !m_addedToWatcher && !m_uri.isEmpty() ) {
326 m_dataMutex.unlock();
329 m_rm->addToWatcher( m_uri );
331 m_addedToWatcher =
true;
335 void Nepomuk2::ResourceData::removeFromWatcher()
337 if( m_addedToWatcher ) {
339 m_dataMutex.unlock();
340 m_rm->removeFromWatcher( m_uri );
342 m_addedToWatcher =
false;
349 QMutexLocker lock(&m_dataMutex);
354 if ( !m_uri.isValid() )
357 const QString oldNaoIdentifier = m_cache[NAO::identifier()].toString();
358 const QUrl oldNieUrl = m_cache[NIE::url()].toUrl();
367 Soprano::QueryResultIterator it =
MAINMODEL->executeQuery(QString(
"select distinct ?p ?o where { "
368 "%1 ?p ?o . }").arg(Soprano::Node::resourceToN3(m_uri)),
369 Soprano::Query::QueryLanguageSparqlNoInference);
370 while ( it.next() ) {
371 QUrl p = it[
"p"].uri();
375 const QString newNaoIdentifier = m_cache.value(NAO::identifier()).toString();
376 const QUrl newNieUrl = m_cache.value(NIE::url()).toUrl();
377 m_cacheDirty =
false;
381 QMutexLocker rmlock(&m_rm->mutex);
382 updateIdentifierLists( oldNaoIdentifier, newNaoIdentifier );
383 updateUrlLists( oldNieUrl, newNieUrl );
391 Q_ASSERT( uri.isValid() );
397 QVariantList varList;
400 if( var.
simpleType() == qMetaTypeId<Resource>() ) {
402 res.determineFinalResourceData();
405 varList << res.
uri();
412 QMutexLocker lock(&m_dataMutex);
414 QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String(
"org.kde.NepomukStorage"),
415 QLatin1String(
"/datamanagement"),
416 QLatin1String(
"org.kde.nepomuk.DataManagement"),
417 QLatin1String(
"setProperty") );
419 msg.setArguments( QVariantList()
423 << KGlobal::mainComponent().componentName() );
425 QDBusConnection bus = KDBusConnectionPool::threadConnection();
426 QDBusMessage reply = bus.call( msg );
427 if( reply.type() == QDBusMessage::ErrorMessage ) {
429 kWarning() << reply.errorMessage();
436 m_cache[uri] = value;
441 updateKickOffLists( uri, oldvalue, value );
448 Q_ASSERT( uri.isValid() );
450 if( value.
isValid() && store() ) {
454 QVariantList varList;
457 if( var.
simpleType() == qMetaTypeId<Resource>() ) {
459 res.determineFinalResourceData();
462 varList << res.
uri();
469 QMutexLocker lock(&m_dataMutex);
470 QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String(
"org.kde.NepomukStorage"),
471 QLatin1String(
"/datamanagement"),
472 QLatin1String(
"org.kde.nepomuk.DataManagement"),
473 QLatin1String(
"addProperty") );
474 msg.setArguments( QVariantList()
478 << KGlobal::mainComponent().componentName() );
480 QDBusConnection bus = KDBusConnectionPool::threadConnection();
481 QDBusMessage reply = bus.call( msg );
482 if( reply.type() == QDBusMessage::ErrorMessage ) {
484 kWarning() << reply.errorMessage();
491 m_cache[uri].append(value);
494 updateKickOffLists( uri, oldvalue, value );
501 Q_ASSERT( uri.isValid() );
502 QMutexLocker lock(&m_dataMutex);
504 if( !m_uri.isEmpty() ) {
505 QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String(
"org.kde.NepomukStorage"),
506 QLatin1String(
"/datamanagement"),
507 QLatin1String(
"org.kde.nepomuk.DataManagement"),
508 QLatin1String(
"removeProperties") );
509 msg.setArguments( QVariantList()
512 << KGlobal::mainComponent().componentName() );
514 QDBusConnection bus = KDBusConnectionPool::threadConnection();
515 QDBusMessage reply = bus.call( msg );
516 if( reply.type() == QDBusMessage::ErrorMessage ) {
518 kWarning() << reply.errorMessage();
524 m_cache.remove( uri );
527 updateKickOffLists( uri, oldvalue,
Variant() );
535 QMutexLocker lock(&m_dataMutex);
537 if( !m_uri.isEmpty() ) {
538 QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String(
"org.kde.NepomukStorage"),
539 QLatin1String(
"/datamanagement"),
540 QLatin1String(
"org.kde.nepomuk.DataManagement"),
541 QLatin1String(
"removeResources") );
542 msg.setArguments( QVariantList()
545 << KGlobal::mainComponent().componentName());
547 QDBusConnection bus = KDBusConnectionPool::threadConnection();
548 QDBusMessage reply = bus.call( msg );
549 if( reply.type() == QDBusMessage::ErrorMessage ) {
551 kWarning() << reply.errorMessage();
562 QMutexLocker lock(&m_dataMutex);
563 if( m_uri.isValid() ) {
564 const QString query = QString::fromLatin1(
"ask { %1 ?p ?o . }")
565 .arg( Soprano::Node::resourceToN3(m_uri) );
566 return MAINMODEL->executeQuery( query, Soprano::Query::QueryLanguageSparql ).boolValue();
576 QMutexLocker lock(&m_dataMutex);
577 return !m_uri.isEmpty() || !m_nieUrl.isEmpty() || !m_naoIdentifier.isEmpty();
582 QMutexLocker lock(&m_dataMutex);
583 if( !m_uri.isEmpty() ) {
612 if( !m_naoIdentifier.isEmpty() ) {
616 QString query = QString::fromLatin1(
"select distinct ?r where { ?r %1 %2. } LIMIT 1")
617 .arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::identifier()) )
618 .arg( Soprano::Node::literalToN3( m_naoIdentifier ) );
620 Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
622 m_uri = it[
"r"].uri();
631 QString query = QString::fromLatin1(
"select distinct ?r ?o where { "
632 "{ ?r %1 %2 . FILTER(?r!=%2) . } "
636 .arg( Soprano::Node::resourceToN3( Nepomuk2::Vocabulary::NIE::url() ) )
637 .arg( Soprano::Node::resourceToN3( m_nieUrl ) );
638 Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
640 QUrl uri = it[
"r"].uri();
641 if( uri.isEmpty() ) {
655 if( !m_uri.isEmpty() ) {
657 QMutexLocker locker(&m_rm->mutex);
660 ResourceDataHash::iterator it = m_rm->m_initializedData.find(m_uri);
661 if( it == m_rm->m_initializedData.end() ) {
662 m_rm->m_initializedData.insert( m_uri,
this );
670 Q_FOREACH (
Resource* res, m_resources) {
671 res->m_data = foundData;
673 foundData->
ref( res );
682 QMutexLocker lock(&m_dataMutex);
693 return( m_uri == other.m_uri &&
694 m_naoIdentifier == other.m_naoIdentifier &&
695 m_nieUrl == other.m_nieUrl );
701 dbg << QString::fromLatin1(
"[uri: %1; url: %2, identifier: %3, ref: %4]")
713 return data.operator<<( dbg );
716 void Nepomuk2::ResourceData::updateUrlLists(
const QUrl& oldUrl,
const QUrl& newUrl)
718 if ( !oldUrl.isEmpty() ) {
719 m_rm->m_urlKickOff.remove( oldUrl );
722 if( !newUrl.isEmpty() ) {
723 m_rm->m_urlKickOff.insert( newUrl,
this );
727 void Nepomuk2::ResourceData::updateIdentifierLists(
const QString& oldIdentifier,
const QString& newIdentifier)
729 if ( !oldIdentifier.isEmpty() ) {
730 m_rm->m_identifierKickOff.remove( oldIdentifier );
733 if( !newIdentifier.isEmpty() ) {
734 m_rm->m_identifierKickOff.insert( newIdentifier,
this );
743 if( uri == NIE::url() || uri == NAO::identifier() ){
744 QMutexLocker rmlock(&m_rm->mutex);
745 if( uri == NIE::url() )
746 updateUrlLists( oldvalue.
toUrl(), newvalue.
toUrl() );
747 else if( uri == NAO::identifier() )
754 bool removeInvalidValues(QList<Nepomuk2::Variant>& vList) {
755 bool modified =
false;
758 vList.removeAll(var);
770 QMutexLocker lock(&m_dataMutex);
772 QList<Variant> vl = m_cache.value(prop.
uri()).toVariantList();
775 if( removeInvalidValues(vl) ) {
776 m_cache[prop.
uri()] = vl;
779 if( vl.contains(value) ) {
784 QMutableListIterator<Variant> it(vl);
785 while( it.hasNext() ) {
791 updateKickOffLists(prop.
uri(), m_cache.value(prop.
uri()),
Variant());
792 m_cache.remove(prop.
uri());
798 updateKickOffLists(prop.
uri(), m_cache.value(prop.
uri()), vl.first());
799 m_cache[prop.
uri()] = vl;
806 QMutexLocker lock(&m_dataMutex);
808 const Variant oldvalue = m_cache.value(prop.
uri());
812 updateKickOffLists(prop.
uri(), oldvalue, var);
817 QMutexLocker lock(&m_dataMutex);
818 if( m_watchEnabled != status ) {
819 m_watchEnabled = status;
829 QMutexLocker lock(&m_dataMutex);
830 return m_watchEnabled;
void updateKickOffLists(const QUrl &uri, const Variant &oldvariant, const Variant &newvariant)
Updates ResourceManagerPrivate's list.
bool isFile()
Tries to determine if this resource represents a file by examining the type and the uri...
QUrl toUrl() const
Convert into a QUrl value.
QUrl uri() const
The URI of the resource.
QVariantList normalizeVariantList(const QVariantList &l)
Replaces KUrl with QUrl for DBus marshalling.
void removeProperty(const QUrl &uri)
QHash< QUrl, Variant > allProperties()
void setWatchEnabled(bool status)
void setProperty(const QUrl &uri, const Variant &value)
Set a property.
QDataStream & operator<<(QDataStream &, const Nepomuk2::SimpleResource &)
QStringList convertUriList(const QList< QUrl > &uris)
Variant property(const QUrl &uri)
void remove(bool recursive=true)
Remove this resource data from the store completely.
bool exists()
This method only works with a proper URI, i.e.
void propertyAdded(const Types::Property &prop, const QVariant &value)
QList< Variant > toVariantList() const
Convert a Variant to a list of Variants.
The Nepomuk Variant extends over QVariant by introducing direct support for Resource embedding...
void addProperty(const QUrl &uri, const Variant &value)
bool store()
Makes sure the resource is present in the RDF store.
bool hasProperty(const QUrl &uri)
Resource toResource() const
Convert into a Resource value.
static Variant fromNode(const Soprano::Node &node)
Create a Variant object from a Soprano::Node.
QString convertUri(const QUrl &uri)
A Class is a resource of type rdf:Class.
A property is a resource of type rdf:Property which relates a domain with a range.
bool isSubClassOf(const Class &other)
Check if this class is derived from another class.
void determineUri()
Searches for the resource in the Nepomuk store using m_kickoffId and m_kickoffUri.
void resetAll()
Will reset this instance to 0 as if constructed without parameters Used by remove() and deleteData() ...
void propertyRemoved(const Types::Property &prop, const QVariant &value)
Called by ResourceManager (with the RM mutex locked)
ResourceData(const QUrl &uri, const QUrl &kickOffUri, const QUrl &type_, ResourceManagerPrivate *rm)
QDebug operator<<(QDebug dbg) const
KJob * setProperty(const QList< QUrl > &resources, const QUrl &property, const QVariantList &values, const KComponentData &component=KGlobal::mainComponent())
Set the values of a property for one or more resources.
QString toString() const
The toString() method is a little more powerful than other toXXX methods since it actually converts a...
Resource is the central object type in Nepomuk.
void append(int i)
Append i to this variant.
QUrl uri() const
The URI of the resource, uniquely identifying it.
bool ref(Nepomuk2::Resource *res)
QUrl uri() const
The URI of the resource.
bool operator==(const ResourceData &other) const
Compares the properties of two ResourceData objects taking into account the Deleted flag...