Page MenuHomePhorge

No OneTemporary

diff --git a/nepomuk/core/resourcedata.cpp b/nepomuk/core/resourcedata.cpp
index 0fd6d03a74..ca151319c3 100644
--- a/nepomuk/core/resourcedata.cpp
+++ b/nepomuk/core/resourcedata.cpp
@@ -1,816 +1,816 @@
/*
* This file is part of the Nepomuk KDE project.
* Copyright (C) 2006-2010 Sebastian Trueg <trueg@kde.org>
* Copyright (C) 2010-2012 Vishesh Handa <handa.vish@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "resourcedata.h"
#include "resourcemanager.h"
#include "resourcemanager_p.h"
#include "resource.h"
#include "tools.h"
#include "nie.h"
#include "nfo.h"
#include "pimo.h"
#include "nepomukmainmodel.h"
#include "dbusconnectionpool.h"
#include "class.h"
#include "dbustypes.h"
#include "resourcewatcher.h"
#include <Soprano/Statement>
#include <Soprano/StatementIterator>
#include <Soprano/QueryResultIterator>
#include <Soprano/Model>
#include <Soprano/Vocabulary/RDFS>
#include <Soprano/Vocabulary/RDF>
#include <Soprano/Vocabulary/Xesam>
#include <Soprano/Vocabulary/NAO>
#include <QtCore/QFile>
#include <QtCore/QDateTime>
#include <QtCore/QMutexLocker>
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusReply>
#include <kdebug.h>
#include <kurl.h>
#include <kcomponentdata.h>
using namespace Soprano;
#define MAINMODEL (m_rm->m_manager->mainModel())
Nepomuk::ResourceData::ResourceData( const QUrl& uri, const QUrl& kickOffUri, const QUrl& type, ResourceManagerPrivate* rm )
: m_uri(uri),
m_mainType( type ),
m_modificationMutex(QMutex::Recursive),
m_cacheDirty(true),
m_pimoThing(0),
m_groundingOccurence(0),
m_rm(rm)
{
if( m_mainType.isEmpty() ) {
m_mainType = Soprano::Vocabulary::RDFS::Resource();
}
m_types << m_mainType;
if( m_rm->dataCacheFull() )
m_rm->cleanupCache();
m_rm->dataCnt.ref();
if( !uri.isEmpty() ) {
m_kickoffUris.insert( uri );
}
if( !kickOffUri.isEmpty() ) {
m_kickoffUris.insert( kickOffUri );
}
m_rm->addToKickOffList( this, m_kickoffUris );
}
Nepomuk::ResourceData::~ResourceData()
{
resetAll(true);
m_rm->dataCnt.deref();
}
bool Nepomuk::ResourceData::isFile()
{
return( m_uri.scheme() == QLatin1String("file") ||
m_nieUrl.scheme() == QLatin1String("file") ||
(!m_kickoffUris.isEmpty() && (*m_kickoffUris.begin()).scheme() == QLatin1String("file")) ||
constHasType( Soprano::Vocabulary::Xesam::File() ) ||
constHasType( Nepomuk::Vocabulary::NFO::FileDataObject() ) );
}
QUrl Nepomuk::ResourceData::uri() const
{
return m_uri;
}
QUrl Nepomuk::ResourceData::type()
{
load();
return m_mainType;
}
QList<QUrl> Nepomuk::ResourceData::allTypes()
{
load();
return m_types;
}
void Nepomuk::ResourceData::setTypes( const QList<QUrl>& types )
{
store();
QMutexLocker lock(&m_modificationMutex);
// reset types
m_types.clear();
m_mainType = Soprano::Vocabulary::RDFS::Resource();
QList<Node> nodes;
// load types (and set maintype)
foreach( const QUrl& url, types ) {
loadType( url );
nodes << Node( url );
}
// update the data store
setProperty(Soprano::Vocabulary::RDF::type(), Nepomuk::Variant(types) );
}
void Nepomuk::ResourceData::resetAll( bool isDelete )
{
// remove us from all caches (store() will re-insert us later if necessary)
m_rm->mutex.lock();
if( !m_uri.isEmpty() ) {
m_rm->m_initializedData.remove( m_uri );
if( m_rm->m_watcher ) {
- m_rm->m_watcher->removeResource(Resource::fromResourceUri(m_uri));
+ m_rm->m_watcher->removeResource(m_uri);
}
}
Q_FOREACH( const KUrl& uri, m_kickoffUris )
m_rm->m_uriKickoffData.remove( uri );
m_rm->mutex.unlock();
// reset all variables
m_uri = QUrl();
m_nieUrl = KUrl();
m_kickoffUris.clear();
m_cache.clear();
m_cacheDirty = false;
m_types.clear();
delete m_pimoThing;
m_pimoThing = 0;
m_groundingOccurence = 0;
// when we are being deleted the value of m_mainType is not important
// anymore. Also since ResourceManager is a global static it might be
// deleted after the global static behind Soprano::Vocabulary::RDFS
// which results in a crash.
if( !isDelete )
m_mainType = Soprano::Vocabulary::RDFS::Resource();
}
QHash<QUrl, Nepomuk::Variant> Nepomuk::ResourceData::allProperties()
{
load();
return m_cache;
}
bool Nepomuk::ResourceData::hasProperty( const QUrl& uri )
{
load();
QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( uri );
if( it == m_cache.constEnd() )
return false;
return true;
}
bool Nepomuk::ResourceData::hasProperty( const QUrl& p, const Variant& v )
{
QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( p );
if( it == m_cache.constEnd() )
return false;
QList<Variant> thisVals = it.value().toVariantList();
QList<Variant> vals = v.toVariantList();
Q_FOREACH( const Variant& val, vals ) {
if( !thisVals.contains(val) )
return false;
}
return true;
}
bool Nepomuk::ResourceData::hasType( const QUrl& uri )
{
load();
return constHasType( uri );
}
bool Nepomuk::ResourceData::constHasType( const QUrl& uri ) const
{
// we need to protect the reading, too. setTypes may be triggered from another thread
QMutexLocker lock(&m_modificationMutex);
Types::Class requestedType( uri );
for ( QList<QUrl>::const_iterator it = m_types.constBegin();
it != m_types.constEnd(); ++it ) {
Types::Class availType( *it );
if ( availType == requestedType ||
availType.isSubClassOf( requestedType ) ) {
return true;
}
}
return false;
}
Nepomuk::Variant Nepomuk::ResourceData::property( const QUrl& uri )
{
load();
// we need to protect the reading, too. load my be triggered from another thread's
// connection to a Soprano statement signal
QMutexLocker lock(&m_modificationMutex);
QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( uri );
if ( it == m_cache.constEnd() ) {
return Variant();
}
else {
return *it;
}
}
bool Nepomuk::ResourceData::store()
{
QMutexLocker lock(&m_modificationMutex);
if ( m_uri.isEmpty() ) {
QMutexLocker rmlock(&m_rm->mutex);
if ( m_nieUrl.isValid() &&
m_nieUrl.isLocalFile() &&
m_mainType == Soprano::Vocabulary::RDFS::Resource() ) {
m_mainType = Nepomuk::Vocabulary::NFO::FileDataObject();
m_types << m_mainType;
}
QDBusConnection bus = QDBusConnection::sessionBus();
QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String("org.kde.nepomuk.DataManagement"),
QLatin1String("/datamanagement"),
QLatin1String("org.kde.nepomuk.DataManagement"),
QLatin1String("createResource") );
QString app = KGlobal::mainComponent().componentName();
QVariantList arguments;
//FIXME: Maybe we should be setting the 'label' over here.
arguments << DBus::convertUriList(m_types) << QString() << QString() << app;
msg.setArguments( arguments );
QDBusMessage reply = bus.call( msg );
if( reply.type() == QDBusMessage::ErrorMessage ) {
//TODO: Set the error somehow
kWarning() << reply.errorMessage();
return false;
}
else if( reply.type() == QDBusMessage::ReplyMessage ) {
m_uri = reply.arguments().at(0).toUrl();
}
// Add us to the initialized data, i.e. make us "valid"
m_rm->m_initializedData.insert( m_uri, this );
// each initialized resource has to be in a kickoff list
// thus, we make sure that is the case.
if( m_kickoffUris.isEmpty() ) {
m_kickoffUris.insert( m_uri );
m_rm->addToKickOffList( this, m_kickoffUris );
}
// store our grounding occurrence in case we are a thing created by the pimoThing() method
if( m_groundingOccurence ) {
if( m_groundingOccurence != this )
m_groundingOccurence->store();
setProperty(Vocabulary::PIMO::groundingOccurrence(), Variant(m_groundingOccurence->uri()) );
}
foreach( const KUrl& url, m_kickoffUris ) {
if( url.scheme().isEmpty() )
setProperty( Soprano::Vocabulary::NAO::identifier(), Variant(url.url()) );
else
setProperty( Nepomuk::Vocabulary::NIE::url(), Variant(url.url()) );
}
}
return true;
}
void Nepomuk::ResourceData::loadType( const QUrl& storedType )
{
if ( !m_types.contains( storedType ) ) {
m_types << storedType;
}
if ( m_mainType == Soprano::Vocabulary::RDFS::Resource() ) {
Q_ASSERT( !storedType.isEmpty() );
m_mainType = storedType;
}
else {
Types::Class currentTypeClass = m_mainType;
Types::Class storedTypeClass = storedType;
// Keep the type that is further down the hierarchy
if ( storedTypeClass.isSubClassOf( currentTypeClass ) ) {
m_mainType = storedTypeClass.uri();
}
else {
// This is a little convenience hack since the user is most likely
// more interested in the file content than the actual file
Types::Class xesamContentClass( Soprano::Vocabulary::Xesam::Content() );
if ( m_mainType == Soprano::Vocabulary::Xesam::File() &&
( storedTypeClass == xesamContentClass ||
storedTypeClass.isSubClassOf( xesamContentClass ) ) ) {
m_mainType = storedTypeClass.uri();
}
else {
// the same is true for nie:DataObject vs. nie:InformationElement
Types::Class nieInformationElementClass( Vocabulary::NIE::InformationElement() );
Types::Class nieDataObjectClass( Vocabulary::NIE::DataObject() );
if( ( currentTypeClass == nieDataObjectClass ||
currentTypeClass.isSubClassOf( nieDataObjectClass ) ) &&
( storedTypeClass == nieInformationElementClass ||
storedTypeClass.isSubClassOf( nieInformationElementClass ) ) ) {
m_mainType = storedTypeClass.uri();
}
}
}
}
}
bool Nepomuk::ResourceData::load()
{
QMutexLocker lock(&m_modificationMutex);
if ( m_cacheDirty ) {
m_cache.clear();
if ( m_uri.isValid() ) {
//
// We exclude properties that are part of the inference graph
// It would only pollute the user interface
//
Soprano::QueryResultIterator it = MAINMODEL->executeQuery(QString("select distinct ?p ?o where { "
"graph ?g { %1 ?p ?o . } . FILTER(?g!=<urn:crappyinference2:inferredtriples>) . "
"}").arg(Soprano::Node::resourceToN3(m_uri)),
Soprano::Query::QueryLanguageSparql);
while ( it.next() ) {
QUrl p = it["p"].uri();
Soprano::Node o = it["o"];
if ( p == Soprano::Vocabulary::RDF::type() ) {
if ( o.isResource() ) {
loadType( o.uri() );
}
}
else {
Nepomuk::Variant var = Variant::fromNode( o );
updateKickOffLists( p, var );
m_cache[p].append( var );
}
}
m_cacheDirty = false;
delete m_pimoThing;
m_pimoThing = 0;
if( hasType( Vocabulary::PIMO::Thing() ) ) {
m_pimoThing = new Thing( m_uri );
}
else {
// TODO: somehow handle pimo:referencingOccurrence and pimo:occurrence
QueryResultIterator pimoIt = MAINMODEL->executeQuery( QString( "select ?r where { ?r <%1> <%2> . }")
.arg( Vocabulary::PIMO::groundingOccurrence().toString() )
.arg( QString::fromAscii( m_uri.toEncoded() ) ),
Soprano::Query::QueryLanguageSparql );
if( pimoIt.next() ) {
m_pimoThing = new Thing( pimoIt.binding("r").uri() );
}
}
return true;
}
else {
return false;
}
}
else {
return true;
}
}
void Nepomuk::ResourceData::setProperty( const QUrl& uri, const Nepomuk::Variant& value )
{
Q_ASSERT( uri.isValid() );
if( store() ) {
// step 0: make sure this resource is in the store
QMutexLocker lock(&m_modificationMutex);
// update the store
QDBusConnection bus = QDBusConnection::sessionBus();
QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String("org.kde.nepomuk.DataManagement"),
QLatin1String("/datamanagement"),
QLatin1String("org.kde.nepomuk.DataManagement"),
QLatin1String("setProperty") );
QString app = KGlobal::mainComponent().componentName();
QVariantList arguments;
QVariantList varList;
foreach( const Nepomuk::Variant var, value.toVariantList() ) {
// make sure resource values are in the store
if( var.simpleType() == qMetaTypeId<Resource>() ) {
var.toResource().m_data->store();
varList << var.toUrl();
}
else {
varList << var.variant();
}
}
arguments << DBus::convertUriList(QList<QUrl>() << m_uri) << DBus::convertUri(uri)
<< QVariant(DBus::normalizeVariantList(varList)) << app;
msg.setArguments( arguments );
QDBusMessage reply = bus.call( msg );
if( reply.type() == QDBusMessage::ErrorMessage ) {
//TODO: Set the error somehow
kWarning() << reply.errorMessage();
return;
}
// update the cache for now
if( value.isValid() )
m_cache[uri] = value;
else
m_cache.remove(uri);
// update the kickofflists
updateKickOffLists( uri, value );
}
}
void Nepomuk::ResourceData::addProperty( const QUrl& uri, const Nepomuk::Variant& value )
{
Q_ASSERT( uri.isValid() );
if( value.isValid() && store() ) {
// step 0: make sure this resource is in the store
QMutexLocker lock(&m_modificationMutex);
// update the store
QDBusConnection bus = QDBusConnection::sessionBus();
QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String("org.kde.nepomuk.DataManagement"),
QLatin1String("/datamanagement"),
QLatin1String("org.kde.nepomuk.DataManagement"),
QLatin1String("addProperty") );
QString app = KGlobal::mainComponent().componentName();
QVariantList arguments;
QVariantList varList;
foreach( const Nepomuk::Variant var, value.toVariantList() ) {
// make sure resource values are in the store
if( var.simpleType() == qMetaTypeId<Resource>() ) {
var.toResource().m_data->store();
varList << var.toUrl();
}
else {
varList << var.variant();
}
}
arguments << DBus::convertUriList(QList<QUrl>() << m_uri) << DBus::convertUri(uri)
<< QVariant(DBus::normalizeVariantList(varList)) << app;
msg.setArguments( arguments );
QDBusMessage reply = bus.call( msg );
if( reply.type() == QDBusMessage::ErrorMessage ) {
//TODO: Set the error somehow
kWarning() << reply.errorMessage();
return;
}
// update the cache for now
if( value.isValid() )
m_cache[uri].append(value);
// update the kickofflists
updateKickOffLists( uri, value );
}
}
void Nepomuk::ResourceData::removeProperty( const QUrl& uri )
{
Q_ASSERT( uri.isValid() );
if( !m_uri.isEmpty() ) {
QMutexLocker lock(&m_modificationMutex);
QDBusConnection bus = QDBusConnection::sessionBus();
QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String("org.kde.nepomuk.DataManagement"),
QLatin1String("/datamanagement"),
QLatin1String("org.kde.nepomuk.DataManagement"),
QLatin1String("removeProperties") );
QString app = KGlobal::mainComponent().componentName();
QVariantList arguments;
arguments << DBus::convertUri(m_uri) << DBus::convertUri(uri) << app;
msg.setArguments( arguments );
QDBusMessage reply = bus.call( msg );
if( reply.type() == QDBusMessage::ErrorMessage ) {
//TODO: Set the error somehow
kWarning() << reply.errorMessage();
return;
}
// Update the cache
m_cache.remove( uri );
// update the kickofflists
updateKickOffLists( uri, Variant() );
}
}
void Nepomuk::ResourceData::remove( bool recursive )
{
Q_UNUSED(recursive)
QMutexLocker lock(&m_modificationMutex);
if( !m_uri.isEmpty() ) {
QDBusConnection bus = QDBusConnection::sessionBus();
QDBusMessage msg = QDBusMessage::createMethodCall( QLatin1String("org.kde.nepomuk.DataManagement"),
QLatin1String("/datamanagement"),
QLatin1String("org.kde.nepomuk.DataManagement"),
QLatin1String("removeResources") );
QString app = KGlobal::mainComponent().componentName();
QVariantList arguments;
// TODO: Set the flag over here
arguments << DBus::convertUri(m_uri) << 0 << app;
msg.setArguments( arguments );
QDBusMessage reply = bus.call( msg );
if( reply.type() == QDBusMessage::ErrorMessage ) {
//TODO: Set the error somehow
kWarning() << reply.errorMessage();
return;
}
}
resetAll();
}
bool Nepomuk::ResourceData::exists()
{
if( m_uri.isValid() ) {
const QString query = QString::fromLatin1("ask { %1 ?p ?o . }")
.arg( Soprano::Node::resourceToN3(m_uri) );
return MAINMODEL->executeQuery( query, Soprano::Query::QueryLanguageSparql ).boolValue();
}
else {
return false;
}
}
bool Nepomuk::ResourceData::isValid() const
{
return( !m_mainType.isEmpty() && ( !m_uri.isEmpty() || !m_kickoffUris.isEmpty() ) );
}
Nepomuk::ResourceData* Nepomuk::ResourceData::determineUri()
{
// We have the following possible situations:
// 1. m_uri is already valid
// -> simple, nothing to do
//
// 2. m_uri is not valid
// -> we need to determine the URI
//
// 2.1. m_kickoffUri is valid
// 2.1.1. it is a file URL
// 2.1.1.1. it is nie:url for r
// -> use r as m_uri
// 2.1.1.2. it points to a file on a removable device for which we have a filex:/ URL
// -> use the r in r nie:url filex:/...
// 2.1.1.3. it is a file which is not an object in some nie:url relation
// -> create new random m_uri and use kickoffUriOrId() as m_nieUrl
// 2.1.2. it is a resource URI
// -> use it as m_uri
//
// 2.2. m_kickOffUri is not valid
// 2.2.1. m_kickOffUri is a nao:identifier for r
// -> use r as m_uri
//
if( m_uri.isEmpty() ) {
Soprano::Model* model = MAINMODEL;
if( !m_kickoffUris.isEmpty() ) {
KUrl kickOffUri = *m_kickoffUris.begin();
if( kickOffUri.scheme().isEmpty() ) {
//
// Not valid. Checking for nao:identifier
//
QString query = QString::fromLatin1("select distinct ?r where { ?r %1 %2. } LIMIT 1")
.arg( Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::identifier()) )
.arg( Soprano::Node::literalToN3( kickOffUri.url() ) );
Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
if( it.next() ) {
m_uri = it["r"].uri();
it.close();
}
}
else {
//
// In one query determine if the URI is already used as resource URI or as
// nie:url
//
QString query = QString::fromLatin1("select distinct ?r ?o where { "
"{ ?r %1 %2 . FILTER(?r!=%2) . } "
"UNION "
"{ %2 ?p ?o . } "
"} LIMIT 1")
.arg( Soprano::Node::resourceToN3( Nepomuk::Vocabulary::NIE::url() ) )
.arg( Soprano::Node::resourceToN3( kickOffUri ) );
Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageSparql );
if( it.next() ) {
QUrl uri = it["r"].uri();
if( uri.isEmpty() ) {
m_uri = kickOffUri;
}
else {
m_uri = uri;
m_nieUrl = kickOffUri;
}
it.close();
}
else if( kickOffUri.scheme() == QLatin1String("nepomuk") ) {
// for nepomuk URIs we simply use the kickoff URI as resource URI
m_uri = kickOffUri;
}
else {
// for everything else we use m_kickoffUri as nie:url with a new random m_uri
m_nieUrl = kickOffUri;
}
}
}
}
//
// Move us to the final data hash now that the URI is known
//
if( !m_uri.isEmpty() ) {
//vHanda: Is there some way to avoid this hash lookup every time?
// It sure would speed things up.
ResourceDataHash::iterator it = m_rm->m_initializedData.find(m_uri);
if( it == m_rm->m_initializedData.end() ) {
m_rm->m_initializedData.insert( m_uri, this );
if(!m_rm->m_watcher) {
m_rm->m_watcher = new ResourceWatcher(m_rm->m_manager);
- QObject::connect( m_rm->m_watcher, SIGNAL(propertyAdded(Nepomuk::Resource, Nepomuk::Types::Property, QVariant)),
- m_rm->m_manager, SLOT(slotPropertyAdded(Nepomuk::Resource, Nepomuk::Types::Property, QVariant)) );
- QObject::connect( m_rm->m_watcher, SIGNAL(propertyRemoved(Nepomuk::Resource, Nepomuk::Types::Property, QVariant)),
- m_rm->m_manager, SLOT(slotPropertyRemoved(Nepomuk::Resource, Nepomuk::Types::Property, QVariant)) );
- m_rm->m_watcher->addResource( Nepomuk::Resource::fromResourceUri(m_uri) );
+ QObject::connect( m_rm->m_watcher, SIGNAL(propertyAdded(QUrl, Nepomuk::Types::Property, QVariant)),
+ m_rm->m_manager, SLOT(slotPropertyAdded(QUrl, Nepomuk::Types::Property, QVariant)) );
+ QObject::connect( m_rm->m_watcher, SIGNAL(propertyRemoved(QUrl, Nepomuk::Types::Property, QVariant)),
+ m_rm->m_manager, SLOT(slotPropertyRemoved(QUrl, Nepomuk::Types::Property, QVariant)) );
+ m_rm->m_watcher->addResource( m_uri );
m_rm->m_watcher->start();
}
else {
- m_rm->m_watcher->addResource( Nepomuk::Resource::fromResourceUri(m_uri) );
+ m_rm->m_watcher->addResource( m_uri );
}
}
else {
return it.value();
}
}
return this;
}
void Nepomuk::ResourceData::invalidateCache()
{
m_cacheDirty = true;
}
Nepomuk::Thing Nepomuk::ResourceData::pimoThing()
{
load();
if( !m_pimoThing ) {
//
// We only create a new thing if we are a nie:InformationElement.
// All other resources will simply be converted into a pimo:Thing
//
// Files, however, are a special case in every aspect. this includes pimo things.
// Files are their own grounding occurrence. This makes a lot of things
// much simpler.
//
if( hasType( Vocabulary::PIMO::Thing() ) ||
isFile() ||
!hasType( Vocabulary::NIE::InformationElement() ) ) {
m_pimoThing = new Thing(this);
}
else {
m_pimoThing = new Thing();
}
m_pimoThing->m_data->m_groundingOccurence = this;
}
return *m_pimoThing;
}
bool Nepomuk::ResourceData::operator==( const ResourceData& other ) const
{
if( this == &other )
return true;
return( m_uri == other.m_uri &&
m_mainType == other.m_mainType &&
m_kickoffUris == other.m_kickoffUris );
}
QDebug Nepomuk::ResourceData::operator<<( QDebug dbg ) const
{
KUrl::List list = m_kickoffUris.toList();
dbg << QString::fromLatin1("[kickoffuri: %1; uri: %2; type: %3; ref: %4]")
.arg( list.toStringList().join(QLatin1String(",")),
m_uri.url(),
m_mainType.toString() )
.arg( m_ref );
return dbg;
}
QDebug operator<<( QDebug dbg, const Nepomuk::ResourceData& data )
{
return data.operator<<( dbg );
}
void Nepomuk::ResourceData::updateKickOffLists(const QUrl& prop, const Nepomuk::Variant& v)
{
KUrl oldUrl;
KUrl newUrl;
if( prop == Nepomuk::Vocabulary::NIE::url() ) {
oldUrl = m_nieUrl;
newUrl = v.toUrl();
m_nieUrl = newUrl;
}
else if( prop == Soprano::Vocabulary::NAO::identifier() ) {
Q_FOREACH( const KUrl& url, m_kickoffUris ) {
if( url.scheme().isEmpty() ) {
oldUrl = url;
break;
}
}
newUrl = KUrl( v.toString() );
}
else {
return;
}
if( oldUrl != newUrl ) {
QMutexLocker rmlock(&m_rm->mutex);
m_kickoffUris.remove( oldUrl );
m_rm->m_uriKickoffData.remove( oldUrl );
if( !newUrl.isEmpty() ) {
m_kickoffUris.insert( newUrl );
m_rm->m_uriKickoffData.insert( newUrl, this );
}
}
}
diff --git a/nepomuk/core/resourcemanager.cpp b/nepomuk/core/resourcemanager.cpp
index 1e0b5ff1c4..f800c443a4 100644
--- a/nepomuk/core/resourcemanager.cpp
+++ b/nepomuk/core/resourcemanager.cpp
@@ -1,569 +1,569 @@
/*
* This file is part of the Nepomuk KDE project.
* Copyright (C) 2006-2012 Sebastian Trueg <trueg@kde.org>
* Copyright (C) 2010 Vishesh Handa <handa.vish@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "resourcemanager.h"
#include "resourcemanager_p.h"
#include "resourcedata.h"
#include "tools.h"
#include "nepomukmainmodel.h"
#include "resource.h"
#include "class.h"
#include "nie.h"
#include "dbustypes.h"
#include "resourcewatcher.h"
#include <kglobal.h>
#include <kdebug.h>
#include <krandom.h>
#include <Soprano/Node>
#include <Soprano/Statement>
#include <Soprano/Vocabulary/RDF>
#include <Soprano/StatementIterator>
#include <Soprano/QueryResultIterator>
#include <QtCore/QFileInfo>
#include <QtCore/QMutex>
#include <QtCore/QMutexLocker>
#include <QtCore/QUuid>
#include <QtCore/QMutableHashIterator>
#include <QtCore/QCoreApplication>
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusConnectionInterface>
#include <QtDBus/QDBusServiceWatcher>
#include <QtDBus/QDBusMetaType>
using namespace Soprano;
Nepomuk::ResourceManager* Nepomuk::ResourceManager::s_instance = 0;
Nepomuk::ResourceManagerPrivate::ResourceManagerPrivate( ResourceManager* manager )
: mainModel( 0 ),
overrideModel( 0 ),
mutex(QMutex::Recursive),
dataCnt( 0 ),
m_manager( manager ),
m_watcher( 0 )
{
Nepomuk::DBus::registerDBusTypes();
}
Nepomuk::ResourceData* Nepomuk::ResourceManagerPrivate::data( const QUrl& uri, const QUrl& type )
{
if ( uri.isEmpty() ) {
// return an invalid resource which may be activated by calling setProperty
return new ResourceData( QUrl(), QUrl(), type, this );
}
if( ResourceData* data = findData( uri ) ) {
return data;
}
else {
return new ResourceData( QUrl(), uri, type, this );
}
}
Nepomuk::ResourceData* Nepomuk::ResourceManagerPrivate::data( const QString& uriOrId, const QUrl& type )
{
if ( !uriOrId.isEmpty() ) {
KUrl url(uriOrId);
return data( url, type );
}
return new ResourceData( QUrl(), QUrl(), type, this );
}
Nepomuk::ResourceData* Nepomuk::ResourceManagerPrivate::dataForResourceUri( const QUrl& uri, const QUrl& type )
{
if ( uri.isEmpty() ) {
// return an invalid resource which may be activated by calling setProperty
return new ResourceData( QUrl(), QUrl(), type, this );
}
if( ResourceData* data = findData( uri ) ) {
return data;
}
else {
return new ResourceData( uri, QUrl(), type, this );
}
}
QList<Nepomuk::ResourceData*> Nepomuk::ResourceManagerPrivate::allResourceDataOfType( const QUrl& type )
{
QList<ResourceData*> l;
if( !type.isEmpty() ) {
mutex.lock();
QSet<ResourceData*> rdl = m_uriKickoffData.values().toSet();
mutex.unlock();
for( QSet<ResourceData*>::iterator rdIt = rdl.begin();
rdIt != rdl.end(); ++rdIt ) {
ResourceData* rd = *rdIt;
//
// make sure we do not trigger a load here since
// 1. that could result in the deletion of values from the iterated list (m_cache.clear() in ResourceData::load)
// 2. We only need to check non-existing resources anyway, since the rest is queried from the db below
//
if( rd->constHasType( type ) ) {
l.append( rd );
}
}
}
return l;
}
QList<Nepomuk::ResourceData*> Nepomuk::ResourceManagerPrivate::allResourceDataWithProperty( const QUrl& uri, const Variant& v )
{
QList<ResourceData*> l;
//
// We need to cache m_uriKickoffData since it might be changed
// in the loop by ResourceData::load()
//
mutex.lock();
QSet<ResourceData*> rdl = m_uriKickoffData.values().toSet();
mutex.unlock();
//
// make sure none of the ResourceData objects are deleted by ResourceData::load below
// which would result in a crash since we have them cached.
//
QList<Resource> tmp;
foreach( ResourceData* rd, rdl ) {
tmp << Resource( rd );
}
for( QSet<ResourceData*>::iterator rdIt = rdl.begin();
rdIt != rdl.end(); ++rdIt ) {
ResourceData* rd = *rdIt;
if( rd->hasProperty( uri ) &&
rd->property( uri ) == v ) {
l.append( rd );
}
}
return l;
}
QList<Nepomuk::ResourceData*> Nepomuk::ResourceManagerPrivate::allResourceData()
{
return m_uriKickoffData.values().toSet().toList();
}
bool Nepomuk::ResourceManagerPrivate::dataCacheFull() const
{
return dataCnt >= 1000;
}
void Nepomuk::ResourceManagerPrivate::cleanupCache( int num )
{
QMutexLocker lock( &mutex );
QSet<ResourceData*> rdl = m_uriKickoffData.values().toSet() + m_initializedData.values().toSet();
for( QSet<ResourceData*>::iterator rdIt = rdl.begin();
rdIt != rdl.end(); ++rdIt ) {
ResourceData* data = *rdIt;
if ( !data->cnt() ) {
delete data;
if( num > 0 && --num == 0 )
break;
}
}
}
bool Nepomuk::ResourceManagerPrivate::shouldBeDeleted( ResourceData * rd ) const
{
//
// We delete data objects in one of two cases:
// 1. They are not valid and as such not in one of the ResourceManagerPrivate kickoff lists
// 2. The cache is already full and we need to clean up
//
return( !rd->cnt() && ( !rd->isValid() || dataCacheFull() ));
}
void Nepomuk::ResourceManagerPrivate::addToKickOffList( ResourceData* rd, const QSet<KUrl> & uris )
{
Q_FOREACH( const KUrl& uri, uris )
m_uriKickoffData.insert( uri, rd );
}
void Nepomuk::ResourceManagerPrivate::_k_storageServiceInitialized( bool success )
{
if( success ) {
kDebug() << "Nepomuk Storage service up and initialized.";
cleanupCache(-1);
m_manager->init();
emit m_manager->nepomukSystemStarted();
}
}
void Nepomuk::ResourceManagerPrivate::_k_dbusServiceUnregistered( const QString& serviceName )
{
if( serviceName == QLatin1String("org.kde.NepomukStorage") ) {
kDebug() << "Nepomuk Storage service went down.";
cleanupCache(-1);
emit m_manager->nepomukSystemStopped();
}
}
Nepomuk::ResourceData* Nepomuk::ResourceManagerPrivate::findData( const QUrl& uri )
{
if ( !uri.isEmpty() ) {
QMutexLocker lock( &mutex );
// look for the URI in the initialized and in the URI kickoff data
ResourceDataHash::iterator end = m_initializedData.end();
ResourceDataHash::iterator it = m_initializedData.find( uri );
if( it == end ) {
end = m_uriKickoffData.end();
it = m_uriKickoffData.find( uri );
}
if( it != end ) {
return it.value();
}
}
return 0;
}
Nepomuk::ResourceManager::ResourceManager()
: QObject(),
d( new ResourceManagerPrivate( this ) )
{
// connect to the storage service's initialized signal to be able to emit
// the nepomukSystemStarted signal
QDBusConnection::sessionBus().connect( QLatin1String("org.kde.NepomukStorage"),
QLatin1String("/servicecontrol"),
QLatin1String("org.kde.nepomuk.ServiceControl"),
QLatin1String("serviceInitialized"),
this,
SLOT(_k_storageServiceInitialized(bool)) );
// connect to the serviceUnregistered signal to be able to connect the nepomukSystemStopped
// signal once the storage service goes away
QDBusServiceWatcher *watcher = new QDBusServiceWatcher( QLatin1String("org.kde.NepomukStorage"),
QDBusConnection::sessionBus(),
QDBusServiceWatcher::WatchForUnregistration,
this );
connect( watcher, SIGNAL(serviceUnregistered(QString)),
this, SLOT(_k_dbusServiceUnregistered(QString)) );
init();
}
Nepomuk::ResourceManager::~ResourceManager()
{
clearCache();
delete d->mainModel;
delete d;
if(s_instance == this) {
s_instance = 0;
}
}
void Nepomuk::ResourceManager::deleteInstance()
{
delete this;
}
Nepomuk::ResourceManager* Nepomuk::ResourceManager::instance()
{
if(!s_instance) {
s_instance = new ResourceManager();
s_instance->setParent(QCoreApplication::instance());
}
return s_instance;
}
int Nepomuk::ResourceManager::init()
{
QMutexLocker lock( &d->initMutex );
if( !d->mainModel ) {
d->mainModel = new MainModel( this );
}
d->mainModel->init();
return d->mainModel->isValid() ? 0 : -1;
}
bool Nepomuk::ResourceManager::initialized() const
{
QMutexLocker lock( &d->initMutex );
return d->mainModel && d->mainModel->isValid();
}
#ifndef KDE_NO_DEPRECATED
Nepomuk::Resource Nepomuk::ResourceManager::createResourceFromUri( const QString& uri )
{
return Resource( uri, QUrl() );
}
#endif
void Nepomuk::ResourceManager::removeResource( const QString& uri )
{
Resource res( uri );
res.remove();
}
void Nepomuk::ResourceManager::notifyError( const QString& uri, int errorCode )
{
kDebug() << "(Nepomuk::ResourceManager) error: " << uri << " " << errorCode;
emit error( uri, errorCode );
}
#ifndef KDE_NO_DEPRECATED
QList<Nepomuk::Resource> Nepomuk::ResourceManager::allResourcesOfType( const QString& type )
{
return allResourcesOfType( QUrl(type) );
}
#endif
QList<Nepomuk::Resource> Nepomuk::ResourceManager::allResourcesOfType( const QUrl& type )
{
QSet<Resource> set;
if( !type.isEmpty() ) {
// check local data
QList<ResourceData*> localData = d->allResourceDataOfType( type );
for( QList<ResourceData*>::iterator rdIt = localData.begin();
rdIt != localData.end(); ++rdIt ) {
Resource res( *rdIt );
set.insert(res);
}
// kDebug() << " added local resources: " << l.count();
Soprano::Model* model = mainModel();
Soprano::StatementIterator it = model->listStatements( Soprano::Statement( Soprano::Node(), Soprano::Vocabulary::RDF::type(), type ) );
while( it.next() ) {
Statement s = *it;
Resource res( s.subject().uri() );
set.insert(res);
}
// kDebug() << " added remote resources: " << l.count();
}
return set.toList();
}
QList<Nepomuk::Resource> Nepomuk::ResourceManager::allResources()
{
QList<Nepomuk::Resource> l;
Q_FOREACH( ResourceData* data, d->allResourceData()) {
l << Resource( data );
}
Soprano::QueryResultIterator it = mainModel()->executeQuery( QLatin1String("select distinct ?r where { ?r a ?t . FILTER(?t != rdf:Property && ?t != rdfs:Class) . }"),
Soprano::Query::QueryLanguageSparql );
while( it.next() ) {
Resource r( it[0].uri() );
l << r;
}
return l;
}
#ifndef KDE_NO_DEPRECATED
QList<Nepomuk::Resource> Nepomuk::ResourceManager::allResourcesWithProperty( const QString& uri, const Variant& v )
{
return allResourcesWithProperty( QUrl(uri), v );
}
#endif
QList<Nepomuk::Resource> Nepomuk::ResourceManager::allResourcesWithProperty( const QUrl& uri, const Variant& v )
{
QSet<Resource> set;
if( v.isList() ) {
kDebug() << "(ResourceManager::allResourcesWithProperty) list values not supported.";
}
else {
// check local data
QList<ResourceData*> localData = d->allResourceDataWithProperty( uri, v );
for( QList<ResourceData*>::iterator rdIt = localData.begin();
rdIt != localData.end(); ++rdIt ) {
set.insert( Resource( *rdIt ) );
}
// check remote data
Soprano::Model* model = mainModel();
Soprano::StatementIterator it = model->listStatements( Soprano::Statement( Soprano::Node(), uri, v.toNode() ) );
while( it.next() ) {
Statement s = *it;
Resource res( s.subject().uri() );
set.insert( res );
}
}
return set.toList();
}
void Nepomuk::ResourceManager::clearCache()
{
d->cleanupCache( -1 );
}
#ifndef KDE_NO_DEPRECATED
QString Nepomuk::ResourceManager::generateUniqueUri()
{
return generateUniqueUri( QString() ).toString();
}
#endif
QUrl Nepomuk::ResourceManager::generateUniqueUri( const QString& name )
{
// default to res URIs
QString type = QLatin1String("res");
// ctx is the only used value for name
if(name == QLatin1String("ctx")) {
type = name;
}
Soprano::Model* model = mainModel();
while( 1 ) {
QString uuid = QUuid::createUuid().toString();
uuid = uuid.mid(1, uuid.length()-2);
QUrl uri = QUrl( QLatin1String("nepomuk:/") + type + QLatin1String("/") + uuid );
if ( !model->executeQuery( QString::fromLatin1("ask where { "
"{ <%1> ?p1 ?o1 . } "
"UNION "
"{ ?s2 <%1> ?o2 . } "
"UNION "
"{ ?s3 ?p3 <%1> . } "
"UNION "
"{ graph <%1> { ?s4 ?4 ?o4 . } . } "
"}")
.arg( QString::fromAscii( uri.toEncoded() ) ), Soprano::Query::QueryLanguageSparql ).boolValue() ) {
return uri;
}
}
}
Soprano::Model* Nepomuk::ResourceManager::mainModel()
{
// make sure we are initialized
if ( !d->overrideModel && !initialized() ) {
init();
}
return d->mainModel;
}
-void Nepomuk::ResourceManager::slotPropertyAdded(const Resource &res, const Types::Property &prop, const QVariant &value)
+void Nepomuk::ResourceManager::slotPropertyAdded(const QUrl &res, const Types::Property &prop, const QVariant &value)
{
- ResourceDataHash::iterator it = d->m_initializedData.find(res.resourceUri());
+ ResourceDataHash::iterator it = d->m_initializedData.find(res);
if(it != d->m_initializedData.end()) {
ResourceData* data = *it;
data->m_cache[prop.uri()].append(Variant(value));
data->updateKickOffLists(prop.uri(), Variant(value));
}
}
-void Nepomuk::ResourceManager::slotPropertyRemoved(const Resource &res, const Types::Property &prop, const QVariant &value_)
+void Nepomuk::ResourceManager::slotPropertyRemoved(const QUrl& res, const Nepomuk::Types::Property& prop, const QVariant& value_)
{
- ResourceDataHash::iterator it = d->m_initializedData.find(res.resourceUri());
+ ResourceDataHash::iterator it = d->m_initializedData.find(res);
if(it != d->m_initializedData.end()) {
ResourceData* data = *it;
QHash<QUrl, Variant>::iterator cacheIt = data->m_cache.find(prop.uri());
if(cacheIt != data->m_cache.end()) {
Variant v = *cacheIt;
const Variant value(value_);
QList<Variant> vl = v.toVariantList();
if(vl.contains(value)) {
vl.removeAll(value);
data->updateKickOffLists(prop.uri(), Variant());
if(vl.isEmpty()) {
data->m_cache.erase(cacheIt);
}
else {
cacheIt.value() = vl;
}
}
}
}
}
void Nepomuk::ResourceManager::setOverrideMainModel( Soprano::Model* model )
{
QMutexLocker lock( &d->mutex );
if( model != d->mainModel ) {
d->overrideModel = model;
// clear cache to make sure we do not mix data
Q_FOREACH( ResourceData* data, d->allResourceData()) {
data->invalidateCache();
}
}
}
Nepomuk::ResourceManager* Nepomuk::ResourceManager::createManagerForModel( Soprano::Model* model )
{
ResourceManager* manager = new ResourceManager();
manager->setOverrideMainModel( model );
return manager;
}
#include "resourcemanager.moc"
diff --git a/nepomuk/core/resourcemanager.h b/nepomuk/core/resourcemanager.h
index 6b23b8f455..c87a803227 100644
--- a/nepomuk/core/resourcemanager.h
+++ b/nepomuk/core/resourcemanager.h
@@ -1,289 +1,289 @@
/*
* This file is part of the Nepomuk KDE project.
* Copyright (C) 2006-2009 Sebastian Trueg <trueg@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef _NEPOMUK_RESOURCE_MANAGER_H_
#define _NEPOMUK_RESOURCE_MANAGER_H_
#include "nepomuk_export.h"
#include <QtCore/QObject>
#include <QtCore/QUrl>
namespace Soprano {
class Model;
}
namespace Nepomuk {
class Resource;
class Variant;
class ResourceManagerHelper;
class ResourceManagerPrivate;
namespace Types {
class Class;
class Property;
}
/**
* \class ResourceManager resourcemanager.h Nepomuk/ResourceManager
*
* \brief The ResourceManager is the central \a %Nepomuk configuration point.
*
* Use the initialized() method to check the availabity of the %Nepomuk system.
* Signals nepomukSystemStarted() and nepomukSystemStopped() can be used to
* enable or disable Nepomuk-specific GUI elements.
*
* \author Sebastian Trueg <trueg@kde.org>
*/
class NEPOMUK_EXPORT ResourceManager : public QObject
{
Q_OBJECT
public:
static ResourceManager* instance();
/**
* In KDE 4.3 support for multiple ResourceManager instances
* has been introduced. To keep binary compatibility both the constructor's
* and destructor's access visibility could not be changed. Thus, instead of deleting
* a custom ResourceManager instance the standard way, one has to call this
* method or use QObject::deleteLater.
*
* \since 4.3
*/
void deleteInstance();
/**
* Initialize the Nepomuk framework. This method will initialize the communication with
* the local Nepomuk-KDE services, ie. the data repository. It will trigger a reconnect
* to the %Nepomuk database.
*
* There is normally no reason to call this method manually except when using multiple
* threads. In that case it is highly recommended to call this method in the main thread
* before doing anything else.
*
* \return 0 if all necessary components could be found and -1 otherwise.
*/
int init();
/**
* \return true if init() has been called successfully, ie. the KMetaData system is connected
* to the local RDF repository service and ready to work.
*/
bool initialized() const;
/**
* Retrieve the main data storage model.
*/
Soprano::Model* mainModel();
/**
* Override the main model used for all storage. By default the main model
* used is the Nepomuk server main model.
*
* \param model The model to use instead of the Nepomuk server or 0 to reset.
*
* \since 4.1
*/
void setOverrideMainModel( Soprano::Model* model );
/**
* \deprecated Use the Resource constructor directly.
*
* Creates a Resource object representing the data referenced by \a uri.
* The result is the same as from using the Resource::Resource( const QString&, const QString& )
* constructor with an empty type.
*
* \return The Resource representing the data at \a uri or an invalid Resource object if the local
* NEPOMUK RDF store does not contain an object with URI \a uri.
*/
#ifndef KDE_NO_DEPRECATED
KDE_DEPRECATED Resource createResourceFromUri( const QString& uri );
#endif
/**
* Remove the resource denoted by \a uri completely.
*
* This method is just a wrapper around Resource::remove. The result
* is the same.
*/
void removeResource( const QString& uri );
/**
* Retrieve a list of all resource managed by this manager.
*
* \warning This list will be very big. Usage of this method is
* discouraged. Use Query::QueryServiceClient in combination with an
* empty Query::Query instead.
*
* \since 4.3
*/
QList<Resource> allResources();
/**
* Retrieve a list of all resources of the specified \a type.
*
* This includes Resources that are not synced yet so it might
* not represent exactly the state as in the RDF store.
*
* \warning This list can be very big. Usage of this method is
* discouraged. Use Query::QueryServiceClient in combination with
* a Query::Query containing one Query::ResourceTypeTerm instead.
*/
QList<Resource> allResourcesOfType( const QUrl& type );
/**
* \deprecated Use allResourcesOfType( const QString& type )
*/
#ifndef KDE_NO_DEPRECATED
KDE_DEPRECATED QList<Resource> allResourcesOfType( const QString& type );
#endif
/**
* Retrieve a list of all resources that have property \a uri defined with a value of \a v.
*
* This includes Resources that are not synced yet so it might
* not represent exactly the state as in the RDF store.
*
* \param uri The URI identifying the property. If this URI does
* not include a namespace the default namespace is
* prepended.
* \param v The value all returned resources should have set as properts \a uri.
*
* \warning This list can be very big. Usage of this method is
* discouraged. Use Query::QueryServiceClient in combination with
* a Query::Query containing one Query::ComparisonTerm instead.
*/
QList<Resource> allResourcesWithProperty( const QUrl& uri, const Variant& v );
/**
* \deprecated Use allResourcesWithProperty( const QString& type )
*/
#ifndef KDE_NO_DEPRECATED
KDE_DEPRECATED QList<Resource> allResourcesWithProperty( const QString& uri, const Variant& v );
#endif
/**
* %ResourceManager caches resource locally so subsequent access is faster.
* This method clears this cache, deleting any Resource that is not used.
*
* \since 4.4
*/
void clearCache();
/**
* \deprecated Use generateUniqueUri(const QString&)
*
* Generates a unique URI that is not used in the store yet. This method ca be used to
* generate URIs for virtual types such as Tag.
*/
#ifndef KDE_NO_DEPRECATED
KDE_DEPRECATED QString generateUniqueUri();
#endif
/**
* Generates a unique URI that is not used in the store yet. This method can be used to
* generate URIs for virtual types such as Tag.
*
* \param label A label that the algorithm should use to try to create a more readable URI.
*
* \return A new unique URI which can be used to define a new resource.
*
* \since 4.2
*/
QUrl generateUniqueUri( const QString& label );
/**
* \internal Non-public API. Used by Resource to signalize errors.
*/
void notifyError( const QString& uri, int errorCode );
/**
* Create a new ResourceManager instance which uses model as its
* override model. This allows to use multiple instances of ResourceManager
* at the same time. Normally one does not need this method as the singleton
* accessed via instance() should be enough.
*
* \param model The model to read and write data from and to.
*
* \since 4.3
*/
static ResourceManager* createManagerForModel( Soprano::Model* model );
Q_SIGNALS:
/**
* This signal gets emitted whenever a Resource changes due to a sync procedure.
* Be aware that modifying resources locally via the Resource::setProperty method
* does not result in a resourceModified signal being emitted.
*
* \param uri The URI of the modified resource.
*
* NOT IMPLEMENTED YET
*/
void resourceModified( const QString& uri );
/**
* Whenever a problem occurs (like for example failed resource syncing) this
* signal is emitted.
*
* \param uri The resource related to the error.
* \param errorCode The type of the error (Resource::ErrorCode)
*/
void error( const QString& uri, int errorCode );
/**
* Emitted once the Nepomuk system is up and can be used.
*
* \warning This signal will not be emitted if the Nepomuk
* system is running when the ResourceManager is created.
* Use initialized() to check the status.
*
* \since 4.4
*/
void nepomukSystemStarted();
/**
* Emitted once the Nepomuk system goes down.
*
* \since 4.4
*/
void nepomukSystemStopped();
private Q_SLOTS:
- void slotPropertyAdded(const Nepomuk::Resource &res, const Nepomuk::Types::Property &prop, const QVariant &value);
- void slotPropertyRemoved(const Nepomuk::Resource &res, const Nepomuk::Types::Property &prop, const QVariant &value);
+ void slotPropertyAdded(const QUrl &res, const Nepomuk::Types::Property &prop, const QVariant &value);
+ void slotPropertyRemoved(const QUrl &res, const Nepomuk::Types::Property &prop, const QVariant &value);
private:
friend class Nepomuk::Resource;
friend class Nepomuk::ResourceManagerPrivate;
ResourceManager();
~ResourceManager();
static ResourceManager* s_instance;
ResourceManagerPrivate* const d;
Q_PRIVATE_SLOT( d, void _k_storageServiceInitialized(bool) )
Q_PRIVATE_SLOT( d, void _k_dbusServiceUnregistered(QString) )
};
}
#endif
diff --git a/nepomuk/core/resourcewatcher.cpp b/nepomuk/core/resourcewatcher.cpp
index 617950320a..d507e1e4ba 100644
--- a/nepomuk/core/resourcewatcher.cpp
+++ b/nepomuk/core/resourcewatcher.cpp
@@ -1,280 +1,274 @@
/*
This file is part of the Nepomuk KDE project.
Copyright (C) 2011 Vishesh Handa <handa.vish@gmail.com>
Copyright (C) 2011 Sebastian Trueg <trueg@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "resourcewatcher.h"
#include "resourcewatcherconnectioninterface.h"
#include "resourcewatchermanagerinterface.h"
#include <QtDBus/QDBusObjectPath>
#include "resource.h"
#include "kurl.h"
#include "kdebug.h"
namespace {
QString convertUri(const QUrl& uri) {
return KUrl(uri).url();
}
QStringList convertUris(const QList<QUrl>& uris) {
QStringList cs;
foreach(const QUrl& uri, uris) {
cs << convertUri(uri);
}
return cs;
}
QList<QUrl> convertUris(const QStringList& uris) {
QList<QUrl> us;
foreach(const QString& uri, uris) {
us << KUrl(uri);
}
return us;
}
}
class Nepomuk::ResourceWatcher::Private {
public:
QList<QUrl> m_types;
QList<QUrl> m_resources;
QList<QUrl> m_properties;
org::kde::nepomuk::ResourceWatcherConnection * m_connectionInterface;
org::kde::nepomuk::ResourceWatcher * m_watchManagerInterface;
};
Nepomuk::ResourceWatcher::ResourceWatcher(QObject* parent)
: QObject(parent),
d(new Private)
{
d->m_watchManagerInterface
= new org::kde::nepomuk::ResourceWatcher( "org.kde.nepomuk.DataManagement",
"/resourcewatcher",
QDBusConnection::sessionBus() );
d->m_connectionInterface = 0;
}
Nepomuk::ResourceWatcher::~ResourceWatcher()
{
stop();
delete d;
}
bool Nepomuk::ResourceWatcher::start()
{
//
// Convert to list of strings
//
QList<QString> uris = convertUris(d->m_resources);
QList<QString> props = convertUris(d->m_properties);
QList<QString> types_ = convertUris(d->m_types);
//
// Create the dbus object to watch
//
QDBusPendingReply<QDBusObjectPath> reply = d->m_watchManagerInterface->watch( uris, props, types_ );
QDBusObjectPath path = reply.value();
if(!path.path().isEmpty()) {
d->m_connectionInterface = new org::kde::nepomuk::ResourceWatcherConnection( "org.kde.nepomuk.DataManagement",
path.path(),
QDBusConnection::sessionBus() );
connect( d->m_connectionInterface, SIGNAL(propertyAdded(QString,QString,QVariantList)),
this, SLOT(slotPropertyAdded(QString,QString,QVariantList)) );
connect( d->m_connectionInterface, SIGNAL(propertyRemoved(QString,QString,QVariantList)),
this, SLOT(slotPropertyRemoved(QString,QString,QVariantList)) );
connect( d->m_connectionInterface, SIGNAL(resourceCreated(QString,QStringList)),
this, SLOT(slotResourceCreated(QString,QStringList)) );
connect( d->m_connectionInterface, SIGNAL(propertyChanged(QString,QString,QVariantList,QVariantList)),
this, SLOT(slotPropertyChanged(QString,QString,QVariantList,QVariantList)) );
connect( d->m_connectionInterface, SIGNAL(resourceRemoved(QString,QStringList)),
this, SLOT(slotResourceRemoved(QString,QStringList)) );
connect( d->m_connectionInterface, SIGNAL(resourceTypeAdded(QString,QString)),
this, SLOT(slotResourceTypeAdded(QString,QString)) );
connect( d->m_connectionInterface, SIGNAL(resourceTypeRemoved(QString,QString)),
this, SLOT(slotResourceTypeRemoved(QString,QString)) );
return true;
}
else {
return false;
}
}
void Nepomuk::ResourceWatcher::stop()
{
if (d->m_connectionInterface) {
d->m_connectionInterface->close();
delete d->m_connectionInterface;
d->m_connectionInterface = 0;
}
}
void Nepomuk::ResourceWatcher::addProperty(const Nepomuk::Types::Property& property)
{
d->m_properties << property.uri();
if(d->m_connectionInterface) {
d->m_connectionInterface->addProperty(convertUri(property.uri()));
}
}
-void Nepomuk::ResourceWatcher::addResource(const Nepomuk::Resource& res)
+void Nepomuk::ResourceWatcher::addResource(const QUrl& res)
{
- d->m_resources << res.resourceUri();
+ d->m_resources << res;
if(d->m_connectionInterface) {
- d->m_connectionInterface->addResource(convertUri(res.resourceUri()));
+ d->m_connectionInterface->addResource(convertUri(res));
}
}
void Nepomuk::ResourceWatcher::addType(const Nepomuk::Types::Class& type)
{
d->m_types << type.uri();
if(d->m_connectionInterface) {
d->m_connectionInterface->addType(convertUri(type.uri()));
}
}
void Nepomuk::ResourceWatcher::removeProperty(const Nepomuk::Types::Property& property)
{
d->m_properties.removeAll(property.uri());
if(d->m_connectionInterface) {
d->m_connectionInterface->removeProperty(convertUri(property.uri()));
}
}
-void Nepomuk::ResourceWatcher::removeResource(const Nepomuk::Resource& res)
+void Nepomuk::ResourceWatcher::removeResource(const QUrl& res)
{
- d->m_resources.removeAll(res.resourceUri());
+ d->m_resources.removeAll(res);
if(d->m_connectionInterface) {
- d->m_connectionInterface->removeResource(convertUri(res.resourceUri()));
+ d->m_connectionInterface->removeResource(convertUri(res));
}
}
void Nepomuk::ResourceWatcher::removeType(const Nepomuk::Types::Class& type)
{
d->m_types.removeAll(type.uri());
if(d->m_connectionInterface) {
d->m_connectionInterface->removeType(convertUri(type.uri()));
}
}
QList< Nepomuk::Types::Property > Nepomuk::ResourceWatcher::properties() const
{
QList< Nepomuk::Types::Property > props;
foreach(const QUrl& uri, d->m_properties)
props << Types::Property(uri);
return props;
}
-QList<Nepomuk::Resource> Nepomuk::ResourceWatcher::resources() const
+QList<QUrl> Nepomuk::ResourceWatcher::resources() const
{
- QList<Nepomuk::Resource> resources;
- foreach(const QUrl& uri, d->m_resources)
- resources << Resource::fromResourceUri(uri);
- return resources;
+ return d->m_resources;
}
QList< Nepomuk::Types::Class > Nepomuk::ResourceWatcher::types() const
{
QList<Nepomuk::Types::Class> types;
foreach(const QUrl& uri, d->m_types)
types << Types::Class(uri);
return types;
}
void Nepomuk::ResourceWatcher::setProperties(const QList< Nepomuk::Types::Property >& properties_)
{
d->m_properties.clear();
foreach(const Nepomuk::Types::Property& p, properties_) {
d->m_properties << p.uri();
}
if(d->m_connectionInterface) {
d->m_connectionInterface->setProperties(convertUris(d->m_properties));
}
}
-void Nepomuk::ResourceWatcher::setResources(const QList< Nepomuk::Resource >& resources_)
+void Nepomuk::ResourceWatcher::setResources(const QList<QUrl>& resources_)
{
- d->m_resources.clear();
- foreach(const Nepomuk::Resource& res, resources_) {
- d->m_resources << res.resourceUri();
- }
+ d->m_resources = resources_;
if(d->m_connectionInterface) {
d->m_connectionInterface->setResources(convertUris(d->m_resources));
}
}
void Nepomuk::ResourceWatcher::setTypes(const QList< Nepomuk::Types::Class >& types_)
{
d->m_types.clear();
foreach(const Nepomuk::Types::Class& t, types_) {
d->m_types << t.uri();
}
if(d->m_connectionInterface) {
d->m_connectionInterface->setTypes(convertUris(d->m_types));
}
}
void Nepomuk::ResourceWatcher::slotResourceCreated(const QString &res, const QStringList &types)
{
- emit resourceCreated(Nepomuk::Resource::fromResourceUri(KUrl(res)), convertUris(types));
+ emit resourceCreated((KUrl(res)), convertUris(types));
}
void Nepomuk::ResourceWatcher::slotResourceRemoved(const QString &res, const QStringList &types)
{
emit resourceRemoved(KUrl(res), convertUris(types));
}
void Nepomuk::ResourceWatcher::slotResourceTypeAdded(const QString &res, const QString &type)
{
emit resourceTypeAdded(KUrl(res), KUrl(type));
}
void Nepomuk::ResourceWatcher::slotResourceTypeRemoved(const QString &res, const QString &type)
{
emit resourceTypeRemoved(KUrl(res), KUrl(type));
}
void Nepomuk::ResourceWatcher::slotPropertyAdded(const QString& res, const QString& prop, const QVariantList &objects)
{
foreach(const QVariant& v, objects) {
- emit propertyAdded( Resource::fromResourceUri(KUrl(res)), Types::Property( KUrl(prop) ), v );
+ emit propertyAdded( KUrl(res), Types::Property( KUrl(prop) ), v );
}
}
void Nepomuk::ResourceWatcher::slotPropertyRemoved(const QString& res, const QString& prop, const QVariantList &objects)
{
foreach(const QVariant& v, objects) {
- emit propertyRemoved( Resource::fromResourceUri(KUrl(res)), Types::Property( KUrl(prop) ), v );
+ emit propertyRemoved( KUrl(res), Types::Property( KUrl(prop) ), v );
}
}
void Nepomuk::ResourceWatcher::slotPropertyChanged(const QString& res, const QString& prop, const QVariantList& oldObjs, const QVariantList& newObjs)
{
- emit propertyChanged( Resource::fromResourceUri(KUrl(res)), Types::Property( KUrl(prop) ),
+ emit propertyChanged( KUrl(res), Types::Property( KUrl(prop) ),
oldObjs, newObjs );
}
#include "resourcewatcher.moc"
diff --git a/nepomuk/core/resourcewatcher.h b/nepomuk/core/resourcewatcher.h
index 06b96229cd..1392920a64 100644
--- a/nepomuk/core/resourcewatcher.h
+++ b/nepomuk/core/resourcewatcher.h
@@ -1,315 +1,315 @@
/*
This file is part of the Nepomuk KDE project.
Copyright (C) 2011 Vishesh Handa <handa.vish@gmail.com>
Copyright (C) 2011 Sebastian Trueg <trueg@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef RESOURCEWATCHER_H
#define RESOURCEWATCHER_H
#include "../types/class.h"
#include "../types/property.h"
#include "resource.h"
#include <QtDBus/QDBusVariant>
#include <QtCore/QVariant>
namespace Nepomuk {
/**
* \class ResourceWatcher resourcewatcher.h
*
* \brief Selectively monitor the nepomuk repository for changes.
*
* Resources may be monitored on the basis of types, properties, and uris.
*
* Changes may be monitored in one of the following ways:
* -# By resources -
* Specify the exact resources that should be watched. Any changes made to the specified resources
* (Excluding \ref nepomuk_dms_metadata) will be notified through the propertyAdded() and propertyRemoved()
* signals. Notifications will also be sent if any of the watched resources is deleted.
* -# By resources and properties -
* Specify the exact resources and their properties. Any changes made to the specified resources
* which touch one of the specified properties will be notified through the propertyAdded() and propertyRemoved()
* signals.
* -# By types -
* Specific types may be specified via add/setType. If types are set, then notifications will be
* sent for all new resources of that type. This includes property changes and resource creation and removal.
* TODO: add flags that allow to only watch for resource creation and removal.
* -# By types and properties -
* Both the types and properties may be specified. Notifications will be sent for property changes
* in resource with the specified types.
*
* \section nepomuk_rw_examples Resource Watcher Usage Example
*
* The following code creates a new ResourceWatcher, configures it to listen to changes on the \c nmm:performer
* property on one specific resource \c res.
*
* \code
* Nepomuk::ResourceWatcher* watcher = new Nepomuk::ResourceWatcher(this);
* watcher->addResource(res);
* watcher->addProperty(NMM:performer());
* connect(watcher, SIGNAL(propertyAdded(Nepomuk::Resource, Nepomuk::Types::Property, QVariant)),
* this, SLOT(slotPropertyChanged()));
* connect(watcher, SIGNAL(propertyRemoved(Nepomuk::Resource, Nepomuk::Types::Property, QVariant)),
* this, SLOT(slotPropertyChanged()));
* rwatcher->start();
* \endcode
*
* \author Vishesh Handa <handa.vish@gmail.com>, Sebastian Trueg <trueg@kde.org>
*
* \ingroup nepomuk_datamanagement
*/
class ResourceWatcher : public QObject
{
Q_OBJECT
public:
/**
* \brief Create a new %ResourceWatcher instance.
*
* This instance will not emit any signals before it has been configured
* and started.
*/
ResourceWatcher( QObject* parent = 0 );
/**
* \brief Destructor.
*/
virtual ~ResourceWatcher();
/**
* \brief Add a type to be watched.
*
* Every resource of this type will be watched for changes.
*
* \sa setTypes()
*/
void addType( const Types::Class & type );
/**
* \brief Add a resource to be watched.
*
* Every change to this resource will be
* signalled, depending on the configured properties().
*
* \sa setResources()
*/
- void addResource( const Nepomuk::Resource & res );
+ void addResource( const QUrl & res );
/**
* \brief Add a property to be watched.
*
* Every change to a value of this property
* will be signalled, depending on the configured resources() or types().
*
* \sa setProperties()
*/
void addProperty( const Types::Property & property );
/**
* \brief Remove a type to be watched.
*
* Every resource of this type will be watched for changes.
*
* \sa setTypes()
*/
void removeType( const Types::Class & type );
/**
* \brief Remove a resource to be watched.
*
* Every change to this resource will be
* signalled, depending on the configured properties().
*
* \sa setResources()
*/
- void removeResource( const Nepomuk::Resource & res );
+ void removeResource( const QUrl & res );
/**
* \brief Remove a property to be watched.
*
* Every change to a value of this property
* will be signalled, depending on the configured resources() or types().
*
* \sa setProperties()
*/
void removeProperty( const Types::Property & property );
/**
* \brief Set the types to be watched.
*
* Every resource having one of these types will be watched for changes.
*
* \sa addType()
*/
void setTypes( const QList<Types::Class> & types_ );
/**
* \brief Set the resources to be watched.
*
* Every change to one of these resources will be
* signalled, depending on the configured properties().
*
* \sa addResource()
*/
- void setResources( const QList<Nepomuk::Resource> & resources_ );
+ void setResources( const QList<QUrl> & resources_ );
/**
* \brief Set the properties to be watched.
*
* Every change to a value of any of these properties
* will be signalled, depending on the configured resources() or types().
*
* \sa addProperty()
*/
void setProperties( const QList<Types::Property> & properties_ );
/**
* \brief The types that have been configured via addType() and setTypes().
*
* Every resource having one of these types will be watched
* for changes.
*/
QList<Types::Class> types() const;
/**
* \brief The resources that have been configured via addResource() and setResources().
*
* Every change to one of these resources will be
* signalled, depending on the configured properties().
*/
- QList<Nepomuk::Resource> resources() const;
+ QList<QUrl> resources() const;
/**
* \brief The properties that have been configured via addProperty() and setProperties().
*
* Every change to a value of any of these properties
* will be signalled, depending on the configured resources() or types().
*/
QList<Types::Property> properties() const;
public Q_SLOTS:
/**
* \brief Start the signalling of changes.
*
* Before calling this method no signal will be emitted. In
* combination with stop() this allows to suspend the watching.
* Calling start() multiple times has no effect.
*/
bool start();
/**
* \brief Stop the signalling of changes.
*
* Allows to stop the watcher which has been started
* via start(). Calling stop() multiple times has no effect.
*/
void stop();
Q_SIGNALS:
/**
* \brief This signal is emitted when a new resource is created.
* \param resource The newly created resource.
* \param types The types the new resource has. If types() have been configured this list will always
* contain one of the configured types.
*/
- void resourceCreated( const Nepomuk::Resource & resource, const QList<QUrl>& types ); //FIXME: Use either Resource or uri, not a mix
+ void resourceCreated( const QUrl & resource, const QList<QUrl>& types ); //FIXME: Use either Resource or uri, not a mix
/**
* \brief This signal is emitted when a resource is deleted.
* \param uri The resource URI of the removed resource.
* \param types The types the removed resource had. If types() have been configured this list will always
* contain one of the configured types.
*/
void resourceRemoved( const QUrl & uri, const QList<QUrl>& types );
/**
* \brief This signal is emitted when a type has been added to a resource. This does not include creation which
* is signalled via resourceCreated(). It only applies to changes in a resource's types.
* \param res The changed resource.
* \param type The newly added type. If types() have been configured it will be one of them.
*/
- void resourceTypeAdded( const Nepomuk::Resource & res, const Types::Class & type );
+ void resourceTypeAdded( const QUrl & res, const Types::Class & type );
/**
* \brief This signal is emitted when a type has been removed from a resource.
*
* This does not include removal of entire resources which is signalled via resourceRemoved().
* It only applies to changes in a resource's types.
* \param res The changed resource.
* \param type The removed type. If types() have been configured it will be one of them.
*/
- void resourceTypeRemoved( const Nepomuk::Resource & res, const Types::Class & type );
+ void resourceTypeRemoved( const QUrl & res, const Types::Class & type );
/**
* \brief This signal is emitted when a property value is added.
* \param resource The changed resource.
* \param property The property which has a new value.
* \param value The newly added property value.
*/
- void propertyAdded( const Nepomuk::Resource & resource,
+ void propertyAdded( const QUrl & resource,
const Nepomuk::Types::Property & property,
const QVariant & value );
/**
* \brief This signal is emitted when a property value is removed.
* \param resource The changed resource.
* \param property The property which was changed.
* \param value The removed property value.
*/
- void propertyRemoved( const Nepomuk::Resource & resource,
+ void propertyRemoved( const QUrl & resource,
const Nepomuk::Types::Property & property,
const QVariant & value );
/**
* \brief This signal is emitted when a property value is changed.
*
* This signal cannot be emitted for all changes. It doesn't work if a property is first
* removed and then set, cause the Data Mangement Service does not maintain an internal
* cache for the purpose of emitting the propertyChanged signal.
*
* Specially, since one could theoretically take forever between the removal and the
* setting of the property.
*
* \param resource The changed resource.
* \param property The property which was changed.
* \param oldValue The removed property value.
*/
- void propertyChanged( const Nepomuk::Resource & resource,
+ void propertyChanged( const QUrl & resource,
const Nepomuk::Types::Property & property,
const QVariantList & oldValue,
const QVariantList & newValue );
private Q_SLOTS:
void slotResourceCreated(const QString& res, const QStringList& types);
void slotResourceRemoved(const QString& res, const QStringList& types);
void slotResourceTypeAdded(const QString& res, const QString& type);
void slotResourceTypeRemoved(const QString& res, const QString& type);
void slotPropertyAdded(const QString& res, const QString& prop, const QVariantList& objects);
void slotPropertyRemoved(const QString& res, const QString& prop, const QVariantList& objects);
void slotPropertyChanged(const QString& res, const QString& prop,
const QVariantList & oldObjs,
const QVariantList & newObjs);
private:
class Private;
Private * d;
};
}
#endif // RESOURCEWATCHER_H

File Metadata

Mime Type
text/x-diff
Expires
Fri, Nov 1, 8:22 AM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
10074948
Default Alt Text
(80 KB)

Event Timeline