Page MenuHomePhorge

No OneTemporary

diff --git a/nepomuk/core/resource.cpp b/nepomuk/core/resource.cpp
index a4ab756d32..75a41a98bc 100644
--- a/nepomuk/core/resource.cpp
+++ b/nepomuk/core/resource.cpp
@@ -1,964 +1,963 @@
/*
* This file is part of the Nepomuk KDE project.
* Copyright (C) 2006-2010 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.
*/
#include "resource.h"
#include "resourcedata.h"
#include "resourcemanager.h"
#include "resourcemanager_p.h"
#include "tools.h"
#include "tag.h"
#include "pimo.h"
#include "thing.h"
#include "file.h"
#include "property.h"
#include "nfo.h"
#include "nie.h"
#include "nco.h"
#include "nuao.h"
#include "klocale.h"
#include "kdebug.h"
#include "kurl.h"
#include "kmimetype.h"
#include <Soprano/Vocabulary/NAO>
#include <Soprano/Vocabulary/Xesam>
#include <Soprano/Vocabulary/RDFS>
#include <Soprano/Model>
#include <Soprano/QueryResultIterator>
Nepomuk::Resource::Resource()
{
QMutexLocker lock( &ResourceManager::instance()->d->mutex );
m_data = ResourceManager::instance()->d->data( QUrl(), QUrl() );
if ( m_data )
m_data->ref( this );
}
Nepomuk::Resource::Resource( ResourceManager* manager )
{
if(!manager)
manager = ResourceManager::instance();
QMutexLocker lock( &manager->d->mutex );
m_data = manager->d->data( QUrl(), QUrl() );
if ( m_data )
m_data->ref( this );
}
Nepomuk::Resource::Resource( const Nepomuk::Resource& res )
{
QMutexLocker lock( &res.m_data->rm()->mutex );
m_data = res.m_data;
if ( m_data )
m_data->ref( this );
}
Nepomuk::Resource::Resource( const QString& uri, const QUrl& type )
{
QMutexLocker lock( &ResourceManager::instance()->d->mutex );
m_data = ResourceManager::instance()->d->data( uri, type );
if ( m_data )
m_data->ref( this );
}
Nepomuk::Resource::Resource( const QString& uri, const QUrl& type, ResourceManager* manager )
{
if(!manager)
manager = ResourceManager::instance();
QMutexLocker lock( &manager->d->mutex );
m_data = manager->d->data( uri, type );
if ( m_data )
m_data->ref( this );
}
#ifndef KDE_NO_DEPRECATED
Nepomuk::Resource::Resource( const QString& uri, const QString& type )
{
QMutexLocker lock( &ResourceManager::instance()->d->mutex );
m_data = ResourceManager::instance()->d->data( uri, type );
if ( m_data )
m_data->ref( this );
}
#endif
Nepomuk::Resource::Resource( const QUrl& uri, const QUrl& type )
{
QMutexLocker lock( &ResourceManager::instance()->d->mutex );
m_data = ResourceManager::instance()->d->data( uri, type );
if ( m_data )
m_data->ref( this );
}
Nepomuk::Resource::Resource( const QUrl& uri, const QUrl& type, ResourceManager* manager )
{
if(!manager)
manager = ResourceManager::instance();
QMutexLocker lock( &manager->d->mutex );
m_data = manager->d->data( uri, type );
if ( m_data )
m_data->ref( this );
}
Nepomuk::Resource::Resource( Nepomuk::ResourceData* data )
{
QMutexLocker lock( &data->rm()->mutex );
m_data = data;
if ( m_data )
m_data->ref( this );
}
Nepomuk::Resource::~Resource()
{
if ( m_data ) {
QMutexLocker lock(&m_data->rm()->mutex);
m_data->deref( this );
if ( m_data->rm()->shouldBeDeleted( m_data ) )
delete m_data;
}
}
Nepomuk::Resource& Nepomuk::Resource::operator=( const Resource& res )
{
if( m_data != res.m_data ) {
QMutexLocker lock(&m_data->rm()->mutex);
if ( m_data && !m_data->deref( this ) && m_data->rm()->shouldBeDeleted( m_data ) ) {
delete m_data;
}
m_data = res.m_data;
if ( m_data )
m_data->ref( this );
}
return *this;
}
Nepomuk::Resource& Nepomuk::Resource::operator=( const QUrl& res )
{
return operator=( Resource( res ) );
}
Nepomuk::ResourceManager* Nepomuk::Resource::manager() const
{
return m_data->rm()->m_manager;
}
#ifndef KDE_NO_DEPRECATED
QString Nepomuk::Resource::uri() const
{
return resourceUri().toString();
}
#endif
QUrl Nepomuk::Resource::resourceUri() const
{
if ( m_data ) {
determineFinalResourceData();
return m_data->uri();
}
else {
return QUrl();
}
}
#ifndef KDE_NO_DEPRECATED
QString Nepomuk::Resource::type() const
{
return resourceType().toString();
}
#endif
QUrl Nepomuk::Resource::resourceType() const
{
determineFinalResourceData();
return m_data->type();
}
QList<QUrl> Nepomuk::Resource::types() const
{
determineFinalResourceData();
return m_data->allTypes();
}
void Nepomuk::Resource::setTypes( const QList<QUrl>& types )
{
determineFinalResourceData();
m_data->setTypes( types );
}
void Nepomuk::Resource::addType( const QUrl& type )
{
QList<QUrl> tl = types();
if( !tl.contains( type ) )
setTypes( tl << type );
}
bool Nepomuk::Resource::hasType( const QUrl& typeUri ) const
{
determineFinalResourceData();
return m_data->hasType( typeUri );
}
QString Nepomuk::Resource::className() const
{
return resourceType().toString().section( QRegExp( "[#:]" ), -1 );
}
QHash<QUrl, Nepomuk::Variant> Nepomuk::Resource::properties() const
{
determineFinalResourceData();
return m_data->allProperties();
}
#ifndef KDE_NO_DEPRECATED
QHash<QString, Nepomuk::Variant> Nepomuk::Resource::allProperties() const
{
QHash<QString, Nepomuk::Variant> pl;
QHash<QUrl, Nepomuk::Variant> p = properties();
QHash<QUrl, Nepomuk::Variant>::const_iterator end = p.constEnd();
for ( QHash<QUrl, Nepomuk::Variant>::const_iterator it = p.constBegin();
it != end; ++it ) {
pl.insert( it.key().toString(), it.value() );
}
return pl;
}
#endif
bool Nepomuk::Resource::hasProperty( const QUrl& uri ) const
{
determineFinalResourceData();
return m_data->hasProperty( uri );
}
bool Nepomuk::Resource::hasProperty( const Types::Property& p, const Variant& v ) const
{
determineFinalResourceData();
return m_data->hasProperty( p.uri(), v );
}
#ifndef KDE_NO_DEPRECATED
bool Nepomuk::Resource::hasProperty( const QString& uri ) const
{
return hasProperty( QUrl( uri ) );
}
#endif
#ifndef KDE_NO_DEPRECATED
Nepomuk::Variant Nepomuk::Resource::property( const QString& uri ) const
{
return property( QUrl( uri ) );
}
#endif
Nepomuk::Variant Nepomuk::Resource::property( const QUrl& uri ) const
{
determineFinalResourceData();
return m_data->property( uri );
}
#ifndef KDE_NO_DEPRECATED
void Nepomuk::Resource::setProperty( const QString& uri, const Nepomuk::Variant& value )
{
setProperty( QUrl( uri ), value );
}
#endif
void Nepomuk::Resource::addProperty( const QUrl& uri, const Variant& value )
{
- Variant v = property( uri );
- v.append( value );
- setProperty( uri, v );
+ determineFinalResourceData();
+ m_data->addProperty( uri, value );
}
void Nepomuk::Resource::setProperty( const QUrl& uri, const Nepomuk::Variant& value )
{
determineFinalResourceData();
m_data->setProperty( uri, value );
}
#ifndef KDE_NO_DEPRECATED
void Nepomuk::Resource::removeProperty( const QString& uri )
{
removeProperty( QUrl( uri ) );
}
#endif
void Nepomuk::Resource::removeProperty( const QUrl& uri )
{
determineFinalResourceData();
m_data->removeProperty( uri );
}
void Nepomuk::Resource::removeProperty( const QUrl& uri, const Variant& value )
{
QList<Variant> vl = property( uri ).toVariantList();
foreach( const Variant& v, value.toVariantList() ) {
vl.removeAll( v );
}
setProperty( uri, Variant( vl ) );
}
void Nepomuk::Resource::remove()
{
determineFinalResourceData();
m_data->remove();
}
bool Nepomuk::Resource::exists() const
{
determineFinalResourceData();
if ( m_data ) {
return m_data->exists();
}
else {
return false;
}
}
bool Nepomuk::Resource::isValid() const
{
return m_data ? m_data->isValid() : false;
}
// TODO: cache this one in ResourceData
QString Nepomuk::Resource::genericLabel() const
{
QString label = this->label();
if(!label.isEmpty())
return label;
label = property( Soprano::Vocabulary::RDFS::label() ).toString();
if(!label.isEmpty())
return label;
label = property( Nepomuk::Vocabulary::NIE::title() ).toString();
if(!label.isEmpty())
return label;
label = property( Nepomuk::Vocabulary::NCO::fullname() ).toString();
if(!label.isEmpty())
return label;
label = property( Soprano::Vocabulary::NAO::identifier() ).toString();
if(!label.isEmpty())
return label;
label = m_data->pimoThing().label();
if(!label.isEmpty())
return label;
label = property( Nepomuk::Vocabulary::NFO::fileName() ).toString();
if(!label.isEmpty())
return label;
const KUrl nieUrl = property( Nepomuk::Vocabulary::NIE::url() ).toUrl();
if(!nieUrl.isEmpty()) {
if(nieUrl.isLocalFile())
return nieUrl.fileName();
else
return nieUrl.prettyUrl();
}
QList<Resource> go = property( Vocabulary::PIMO::groundingOccurrence() ).toResourceList();
if( !go.isEmpty() ) {
label = go.first().genericLabel();
if( label != KUrl(go.first().resourceUri()).pathOrUrl() ) {
return label;
}
}
QString hashValue = property( Vocabulary::NFO::hashValue() ).toString();
if( !hashValue.isEmpty() )
return hashValue;
// ugly fallback
return KUrl(resourceUri()).pathOrUrl();
}
QString Nepomuk::Resource::genericDescription() const
{
QString s = property( Soprano::Vocabulary::NAO::description() ).toString();
if ( !s.isEmpty() ) {
return s;
}
s = property( Soprano::Vocabulary::Xesam::summary() ).toString();
if ( !s.isEmpty() ) {
return s;
}
s = property( Soprano::Vocabulary::Xesam::description() ).toString();
if ( !s.isEmpty() ) {
return s;
}
s = property( Soprano::Vocabulary::Xesam::asText() ).toString();
if ( !s.isEmpty() ) {
return s;
}
s = property( Soprano::Vocabulary::RDFS::comment() ).toString();
return s;
}
QString Nepomuk::Resource::genericIcon() const
{
// FIXME: support resource symbols
Variant symbol = property( Soprano::Vocabulary::NAO::hasSymbol() );
if ( symbol.isString() ) {
return symbol.toString();
} else if ( symbol.isStringList() ) {
const QStringList l = symbol.toStringList();
if ( l.isEmpty() )
return QString();
return l.first();
}
// strigi mimetypes are sadly not very reliable, I keep the code here for future use
// QString mimeType = property( Soprano::Vocabulary::Xesam::mimeType() ).toString();
// if ( !mimeType.isEmpty() ) {
// if ( KMimeType::Ptr m = KMimeType::mimeType( mimeType ) ) {
// return m->iconName();
// }
// }
if ( hasType( Soprano::Vocabulary::Xesam::File() ) ||
resourceUri().scheme() == "file" ) {
return KMimeType::iconNameForUrl( resourceUri() );
}
return QString();
}
Nepomuk::Thing Nepomuk::Resource::pimoThing()
{
determineFinalResourceData();
return m_data->pimoThing();
}
bool Nepomuk::Resource::operator==( const Resource& other ) const
{
if( this == &other )
return true;
if( this->m_data == other.m_data )
return true;
if ( !m_data || !other.m_data ) {
return false;
}
// get the resource URIs since two different ResourceData instances
// can still represent the same Resource
determineFinalResourceData();
other.determineFinalResourceData();
if( m_data->uri().isEmpty() )
return *m_data == *other.m_data;
else
return resourceUri() == other.resourceUri();
}
bool Nepomuk::Resource::operator!=( const Resource& other ) const
{
return !operator==( other );
}
QString Nepomuk::errorString( ErrorCode code )
{
switch( code ) {
case NoError:
return i18n("Success");
case CommunicationError:
return i18n("Communication error");
case InvalidType:
return i18n("Invalid type in Database");
default:
return i18n("Unknown error");
}
}
QString Nepomuk::Resource::description() const
{
return ( property( Soprano::Vocabulary::NAO::description() ).toStringList() << QString() ).first();
}
void Nepomuk::Resource::setDescription( const QString& value )
{
setProperty( Soprano::Vocabulary::NAO::description(), Variant( value ) );
}
QString Nepomuk::Resource::descriptionUri()
{
return Soprano::Vocabulary::NAO::description().toString();
}
QStringList Nepomuk::Resource::identifiers() const
{
return property( Soprano::Vocabulary::NAO::identifier() ).toStringList();
}
void Nepomuk::Resource::setIdentifiers( const QStringList& value )
{
setProperty( Soprano::Vocabulary::NAO::identifier(), Variant( value ) );
}
void Nepomuk::Resource::addIdentifier( const QString& value )
{
Variant v = property( Soprano::Vocabulary::NAO::identifier() );
v.append( value );
setProperty( Soprano::Vocabulary::NAO::identifier(), v );
}
QString Nepomuk::Resource::identifierUri()
{
return Soprano::Vocabulary::NAO::identifier().toString();
}
QStringList Nepomuk::Resource::altLabels() const
{
return property( Soprano::Vocabulary::NAO::altLabel() ).toStringList();
}
void Nepomuk::Resource::setAltLabels( const QStringList& value )
{
setProperty( Soprano::Vocabulary::NAO::altLabel(), Variant( value ) );
}
void Nepomuk::Resource::addAltLabel( const QString& value )
{
Variant v = property( Soprano::Vocabulary::NAO::altLabel() );
v.append( value );
setProperty( Soprano::Vocabulary::NAO::altLabel(), v );
}
QString Nepomuk::Resource::altLabelUri()
{
return Soprano::Vocabulary::NAO::altLabel().toString();
}
QList<Nepomuk::Resource> Nepomuk::Resource::annotations() const
{
// We always store all Resource types as plain Resource objects.
// It does not introduce any overhead (due to the implicit sharing of
// the data and has the advantage that we can mix setProperty calls
// with the special Resource subclass methods.
// More importantly Resource loads the data as Resource objects anyway.
return convertResourceList<Resource>( property( Soprano::Vocabulary::NAO::annotation() ).toResourceList() );
}
void Nepomuk::Resource::setAnnotations( const QList<Nepomuk::Resource>& value )
{
setProperty( Soprano::Vocabulary::NAO::annotation(), Variant( value ) );
}
void Nepomuk::Resource::addAnnotation( const Nepomuk::Resource& value )
{
// We always store all Resource types as plain Resource objects.
// It does not introduce any overhead (due to the implicit sharing of
// the data and has the advantage that we can mix setProperty calls
// with the special Resource subclass methods.
// More importantly Resource loads the data as Resource objects anyway.
Variant v = property( Soprano::Vocabulary::NAO::annotation() );
v.append( Resource( value ) );
setProperty( Soprano::Vocabulary::NAO::annotation(), v );
}
QString Nepomuk::Resource::annotationUri()
{
return Soprano::Vocabulary::NAO::annotation().toString();
}
QList<Nepomuk::Tag> Nepomuk::Resource::tags() const
{
// We always store all Resource types as plain Resource objects.
// It does not introduce any overhead (due to the implicit sharing of
// the data and has the advantage that we can mix setProperty calls
// with the special Resource subclass methods.
// More importantly Resource loads the data as Resource objects anyway.
return convertResourceList<Tag>( property( Soprano::Vocabulary::NAO::hasTag() ).toResourceList() );
}
void Nepomuk::Resource::setTags( const QList<Nepomuk::Tag>& value )
{
// We always store all Resource types as plain Resource objects.
// It does not introduce any overhead (due to the implicit sharing of
// the data and has the advantage that we can mix setProperty calls
// with the special Resource subclass methods.
// More importantly Resource loads the data as Resource objects anyway.
QList<Resource> l;
for( QList<Tag>::const_iterator it = value.constBegin();
it != value.constEnd(); ++it ) {
l.append( Resource( (*it) ) );
}
setProperty( Soprano::Vocabulary::NAO::hasTag(), Variant( l ) );
}
void Nepomuk::Resource::addTag( const Nepomuk::Tag& value )
{
// We always store all Resource types as plain Resource objects.
// It does not introduce any overhead (due to the implicit sharing of
// the data and has the advantage that we can mix setProperty calls
// with the special Resource subclass methods.
// More importantly Resource loads the data as Resource objects anyway.
Variant v = property( Soprano::Vocabulary::NAO::hasTag() );
v.append( Resource( value ) );
setProperty( Soprano::Vocabulary::NAO::hasTag(), v );
}
QString Nepomuk::Resource::tagUri()
{
return Soprano::Vocabulary::NAO::hasTag().toString();
}
QList<Nepomuk::Resource> Nepomuk::Resource::topics() const
{
// We always store all Resource types as plain Resource objects.
// It does not introduce any overhead (due to the implicit sharing of
// the data and has the advantage that we can mix setProperty calls
// with the special Resource subclass methods.
// More importantly Resource loads the data as Resource objects anyway.
return convertResourceList<Resource>( property( Soprano::Vocabulary::NAO::hasTopic() ).toResourceList() );
}
void Nepomuk::Resource::setTopics( const QList<Nepomuk::Resource>& value )
{
setProperty( Soprano::Vocabulary::NAO::hasTopic(), Variant( value ) );
}
void Nepomuk::Resource::addTopic( const Nepomuk::Resource& value )
{
// We always store all Resource types as plain Resource objects.
// It does not introduce any overhead (due to the implicit sharing of
// the data and has the advantage that we can mix setProperty calls
// with the special Resource subclass methods.
// More importantly Resource loads the data as Resource objects anyway.
Variant v = property( Soprano::Vocabulary::NAO::hasTopic() );
v.append( Resource( value ) );
setProperty( Soprano::Vocabulary::NAO::hasTopic(), v );
}
QString Nepomuk::Resource::topicUri()
{
return Soprano::Vocabulary::NAO::hasTopic().toString();
}
QList<Nepomuk::Resource> Nepomuk::Resource::isTopicOfs() const
{
// We always store all Resource types as plain Resource objects.
// It does not introduce any overhead (due to the implicit sharing of
// the data and has the advantage that we can mix setProperty calls
// with the special Resource subclass methods.
// More importantly Resource loads the data as Resource objects anyway.
return convertResourceList<Resource>( property( Soprano::Vocabulary::NAO::isTopicOf() ).toResourceList() );
}
void Nepomuk::Resource::setIsTopicOfs( const QList<Nepomuk::Resource>& value )
{
setProperty( Soprano::Vocabulary::NAO::isTopicOf(), Variant( value ) );
}
void Nepomuk::Resource::addIsTopicOf( const Nepomuk::Resource& value )
{
// We always store all Resource types as plain Resource objects.
// It does not introduce any overhead (due to the implicit sharing of
// the data and has the advantage that we can mix setProperty calls
// with the special Resource subclass methods.
// More importantly Resource loads the data as Resource objects anyway.
Variant v = property( Soprano::Vocabulary::NAO::isTopicOf() );
v.append( Resource( value ) );
setProperty( Soprano::Vocabulary::NAO::isTopicOf(), v );
}
QString Nepomuk::Resource::isTopicOfUri()
{
return Soprano::Vocabulary::NAO::isTopicOf().toString();
}
QList<Nepomuk::Resource> Nepomuk::Resource::isRelateds() const
{
// We always store all Resource types as plain Resource objects.
// It does not introduce any overhead (due to the implicit sharing of
// the data and has the advantage that we can mix setProperty calls
// with the special Resource subclass methods.
// More importantly Resource loads the data as Resource objects anyway.
return convertResourceList<Resource>( property( Soprano::Vocabulary::NAO::isRelated() ).toResourceList() );
}
void Nepomuk::Resource::setIsRelateds( const QList<Nepomuk::Resource>& value )
{
setProperty( Soprano::Vocabulary::NAO::isRelated(), Variant( value ) );
}
void Nepomuk::Resource::addIsRelated( const Nepomuk::Resource& value )
{
// We always store all Resource types as plain Resource objects.
// It does not introduce any overhead (due to the implicit sharing of
// the data and has the advantage that we can mix setProperty calls
// with the special Resource subclass methods.
// More importantly Resource loads the data as Resource objects anyway.
Variant v = property( Soprano::Vocabulary::NAO::isRelated() );
v.append( Resource( value ) );
setProperty( Soprano::Vocabulary::NAO::isRelated(), v );
}
QString Nepomuk::Resource::isRelatedUri()
{
return Soprano::Vocabulary::NAO::isRelated().toString();
}
QString Nepomuk::Resource::label() const
{
return ( property( Soprano::Vocabulary::NAO::prefLabel() ).toStringList() << QString() ).first();
}
void Nepomuk::Resource::setLabel( const QString& value )
{
setProperty( Soprano::Vocabulary::NAO::prefLabel(), Variant( value ) );
}
QString Nepomuk::Resource::labelUri()
{
return Soprano::Vocabulary::NAO::prefLabel().toString();
}
quint32 Nepomuk::Resource::rating() const
{
return ( property( Soprano::Vocabulary::NAO::numericRating() ).toUnsignedIntList() << 0 ).first();
}
void Nepomuk::Resource::setRating( const quint32& value )
{
setProperty( Soprano::Vocabulary::NAO::numericRating(), Variant( value ) );
}
QString Nepomuk::Resource::ratingUri()
{
return Soprano::Vocabulary::NAO::numericRating().toString();
}
QStringList Nepomuk::Resource::symbols() const
{
return property( Soprano::Vocabulary::NAO::hasSymbol() ).toStringList();
}
void Nepomuk::Resource::setSymbols( const QStringList& value )
{
setProperty( Soprano::Vocabulary::NAO::hasSymbol(), Variant( value ) );
}
void Nepomuk::Resource::addSymbol( const QString& value )
{
Variant v = property( Soprano::Vocabulary::NAO::hasSymbol() );
v.append( value );
setProperty( Soprano::Vocabulary::NAO::hasSymbol(), v );
}
QString Nepomuk::Resource::symbolUri()
{
return Soprano::Vocabulary::NAO::hasSymbol().toString();
}
QList<Nepomuk::Resource> Nepomuk::Resource::annotationOf() const
{
return convertResourceList<Resource>( manager()->allResourcesWithProperty( Soprano::Vocabulary::NAO::annotation(), *this ) );
}
QList<Nepomuk::Resource> Nepomuk::Resource::isRelatedOf() const
{
return convertResourceList<Resource>( manager()->allResourcesWithProperty( Soprano::Vocabulary::NAO::isRelated(), *this ) );
}
// static
QList<Nepomuk::Resource> Nepomuk::Resource::allResources()
{
return Nepomuk::convertResourceList<Resource>( ResourceManager::instance()->allResourcesOfType( Soprano::Vocabulary::RDFS::Resource() ) );
}
int Nepomuk::Resource::usageCount() const
{
return property( Vocabulary::NUAO::usageCount() ).toInt();
}
void Nepomuk::Resource::increaseUsageCount()
{
int cnt = 0;
const QDateTime now = QDateTime::currentDateTime();
if( hasProperty( Vocabulary::NUAO::usageCount() ) )
cnt = property( Vocabulary::NUAO::usageCount() ).toInt();
else
setProperty( Vocabulary::NUAO::firstUsage(), now );
++cnt;
setProperty( Vocabulary::NUAO::usageCount(), cnt );
setProperty( Vocabulary::NUAO::lastUsage(), now );
}
bool Nepomuk::Resource::isFile() const
{
if( m_data ) {
determineFinalResourceData();
m_data->load();
return m_data->isFile();
}
else {
return false;
}
}
Nepomuk::File Nepomuk::Resource::toFile() const
{
return File( *this );
}
// static
Nepomuk::Resource Nepomuk::Resource::fromResourceUri( const KUrl& uri, const Nepomuk::Types::Class& type, ResourceManager* manager )
{
if( !manager )
manager = ResourceManager::instance();
QMutexLocker lock( &manager->d->mutex );
return Resource( manager->d->dataForResourceUri( uri, type.uri() ) );
}
void Nepomuk::Resource::determineFinalResourceData() const
{
QMutexLocker lock( &m_data->rm()->mutex );
// Get an initialized ResourceData instance
ResourceData* oldData = m_data;
ResourceData* newData = m_data->determineUri();
Q_ASSERT(oldData);
Q_ASSERT(newData);
// in case we get an already existing one we update all instances
// using the old ResourceData to avoid the overhead of calling
// determineUri over and over
if( newData != oldData ) {
Q_FOREACH( Resource* res, m_data->m_resources) {
res->m_data = newData;
oldData->deref( res );
newData->ref( res );
}
}
if ( !oldData->cnt() )
delete oldData;
}
uint Nepomuk::qHash( const Resource& res )
{
return qHash(res.resourceUri());
}
diff --git a/nepomuk/core/resourcedata.cpp b/nepomuk/core/resourcedata.cpp
index 06c4d7e7ef..c9816bf2ed 100644
--- a/nepomuk/core/resourcedata.cpp
+++ b/nepomuk/core/resourcedata.cpp
@@ -1,750 +1,799 @@
/*
* This file is part of the Nepomuk KDE project.
* Copyright (C) 2006-2010 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 "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 <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 );
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 );
}
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/resourcedata.h b/nepomuk/core/resourcedata.h
index 461b225a56..be4f0a5bc7 100644
--- a/nepomuk/core/resourcedata.h
+++ b/nepomuk/core/resourcedata.h
@@ -1,217 +1,219 @@
/*
* This file is part of the Nepomuk KDE project.
* Copyright (C) 2006-2010 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_DATA_H_
#define _NEPOMUK_RESOURCE_DATA_H_
#include <QtCore/QString>
#include <QtCore/QList>
#include <QtCore/QHash>
#include <QtCore/QMutex>
#include <QtCore/QAtomicInt>
#include <QtCore/QSet>
#include "variant.h"
#include "thing.h"
#include <kurl.h>
#include <soprano/statement.h>
namespace Nepomuk {
class Resource;
class ResourceManagerPrivate;
class ResourceData
{
public:
explicit ResourceData( const QUrl& uri, const QUrl& kickOffUri, const QUrl& type_, ResourceManagerPrivate* rm );
~ResourceData();
inline bool ref(Nepomuk::Resource* res) {
m_resources.push_back( res );
return m_ref.ref();
}
inline bool deref(Nepomuk::Resource* res) {
m_resources.removeAll( res );
return m_ref.deref();
}
inline int cnt() const {
return m_ref;
}
/**
* Tries to determine if this resource represents a file by examining the type and the uri.
*/
bool isFile();
/**
* The URI of the resource. This might be empty if the resource was not synced yet.
*/
QUrl uri() const;
/**
* \return The main type of the resource. ResourceData tries hard to make this the
* most important type, i.e. that which is furthest down the hierachy.
*/
QUrl type();
QList<QUrl> allTypes();
void setTypes( const QList<QUrl>& types );
QHash<QUrl, Variant> allProperties();
bool hasProperty( const QUrl& uri );
bool hasProperty( const QUrl& p, const Variant& v );
/**
* Does also check for subClass relations.
*/
bool hasType( const QUrl& uri );
/**
* Check the type without loading data from the store.
*/
bool constHasType( const QUrl& type ) const;
Variant property( const QUrl& uri );
/**
* Set a property. The property will directly be saved to the RDF store.
* Calls store to make sure this resource and property resources are properly
* stored.
*/
void setProperty( const QUrl& uri, const Variant& value );
+ void addProperty( const QUrl& uri, const Variant& value );
+
void removeProperty( const QUrl& uri );
/**
* Makes sure the resource is present in the RDF store. This means that if it does
* not exist the type and the identifier (if one has been used to create the instance)
* are stored.
*
* This is also the only place where a new URI is generated via ResourceManager::generateUniqueUri()
* in case m_uri is empty.
*
* \sa exists, setProperty
*/
bool store();
bool load();
/**
* Remove this resource data from the store completely.
* \param recursive If true all statements that contain this
* resource as an object will be removed, too.
*/
void remove( bool recursive = true );
/**
* This method only works with a proper URI, i.e. it does
* not work on non-initialized resources that only know
* their kickoffUriOrId
*/
bool exists();
bool isValid() const;
/**
* Searches for the resource in the Nepomuk store using m_kickoffId and m_kickoffUri.
*
* This will either get the actual resource URI from the database
* and add m_data into ResourceManagerPrivate::m_initializedData
* or it will find another ResourceData instance in m_initializedData
* which represents the same resource. The ResourceData that should be
* used is returned.
*
* \returns The initialized ResourceData object representing the actual resource.
*
* m_determineUriMutex needs to be locked before calling this method
*/
ResourceData* determineUri();
void invalidateCache();
Thing pimoThing();
/**
* Compares the properties of two ResourceData objects taking into account the Deleted flag
*/
bool operator==( const ResourceData& other ) const;
QDebug operator<<( QDebug dbg ) const;
ResourceManagerPrivate* rm() const { return m_rm; }
/// Contains a list of resources which use this ResourceData
QList<Resource*> m_resources;
/// the URI that was used to construct the resource. Will be used by determineUri
/// to find the actual resource URI which is either m_kickoffUri itself or
/// a resource URI which relates to m_kickoffUri by nie:url
/// This is a set since Resource::determineFinalResourceData may add additional uris
QSet<KUrl> m_kickoffUris;
private:
void loadType( const QUrl& type );
/// Will reset this instance to 0 as if constructed without parameters
/// Used by remove() and deleteData()
void resetAll( bool isDelete = false );
/// Updates both m_kickoffUris and ResourceMangerPrivate's list
void updateKickOffLists( const QUrl & prop, const Variant & v );
/// final resource URI created by determineUri
KUrl m_uri;
/// the URL of file resources
KUrl m_nieUrl;
QUrl m_mainType;
QList<QUrl> m_types;
QAtomicInt m_ref;
mutable QMutex m_modificationMutex;
QHash<QUrl, Variant> m_cache;
bool m_cacheDirty;
// using a pointer to avoid infinite creation loop
Thing* m_pimoThing;
// only used for delayed storage of the pimo thing relation
ResourceData* m_groundingOccurence;
ResourceManagerPrivate* m_rm;
};
}
QDebug operator<<( QDebug dbg, const Nepomuk::ResourceData& );
#endif

File Metadata

Mime Type
text/x-diff
Expires
Fri, Nov 1, 8:18 AM (1 d, 5 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
10074888
Default Alt Text
(60 KB)

Event Timeline