diff --git a/nepomuk/core/generated/resource.cpp b/nepomuk/core/generated/resource.cpp index b6f20ed1be..0b3e19e1f4 100644 --- a/nepomuk/core/generated/resource.cpp +++ b/nepomuk/core/generated/resource.cpp @@ -1,639 +1,639 @@ /* * This file is part of the Nepomuk KDE project. * Copyright (C) 2006 Sebastian Trueg * * 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 "tools.h" #include #include #include #include #include #include // FIXME: let the code generator do this #include "tag.h" Nepomuk::Resource::Resource() - : m_data( 0 ) { + m_data = ResourceData::data( QUrl(), QUrl() ); } Nepomuk::Resource::Resource( const Nepomuk::Resource& res ) { m_data = res.m_data; if ( m_data ) m_data->ref(); } Nepomuk::Resource::Resource( const QString& uri, const QUrl& type ) { m_data = ResourceData::data( uri, type ); if ( m_data ) m_data->ref(); } Nepomuk::Resource::Resource( const QString& uri, const QString& type ) { m_data = ResourceData::data( uri, type ); if ( m_data ) m_data->ref(); } Nepomuk::Resource::Resource( const QUrl& uri, const QUrl& type ) { m_data = ResourceData::data( uri, type ); if ( m_data ) m_data->ref(); } Nepomuk::Resource::Resource( Nepomuk::ResourceData* data ) { m_data = data; if ( m_data ) data->ref(); } Nepomuk::Resource::~Resource() { if( m_data && m_data->deref() == 0 ) { // m_data->deleteData(); } } Nepomuk::Resource& Nepomuk::Resource::operator=( const Resource& res ) { if( m_data != res.m_data ) { if ( m_data && m_data->deref() == 0 ) { // m_data->deleteData(); } m_data = res.m_data; if ( m_data ) m_data->ref(); } return *this; } QString Nepomuk::Resource::uri() const { return resourceUri().toString(); } QUrl Nepomuk::Resource::resourceUri() const { if ( m_data ) { m_data->determineUri(); return m_data->uri(); } else { return QUrl(); } } QString Nepomuk::Resource::type() const { return resourceType().toString(); } QUrl Nepomuk::Resource::resourceType() const { if ( m_data ) { return m_data->type(); } else { return QUrl(); } } QList Nepomuk::Resource::types() const { if ( m_data ) { return m_data->allTypes(); } else { return QList(); } } bool Nepomuk::Resource::hasType( const QUrl& typeUri ) const { return m_data ? m_data->hasType( typeUri ) : false; } QString Nepomuk::Resource::className() const { return resourceType().toString().section( QRegExp( "[#:]" ), -1 ); } QHash Nepomuk::Resource::allProperties() const { if ( m_data ) { return m_data->allProperties(); } else { return QHash(); } } bool Nepomuk::Resource::hasProperty( const QString& uri ) const { return m_data ? m_data->hasProperty( uri ) : false; } Nepomuk::Variant Nepomuk::Resource::property( const QString& uri ) const { if ( m_data ) { return m_data->property( uri ); } else { return Variant(); } } void Nepomuk::Resource::setProperty( const QString& uri, const Nepomuk::Variant& value ) { if ( m_data ) { m_data->setProperty( uri, value ); } } void Nepomuk::Resource::removeProperty( const QString& uri ) { if ( m_data ) { m_data->removeProperty( uri ); } } void Nepomuk::Resource::remove() { if ( m_data ) { m_data->remove(); } } bool Nepomuk::Resource::exists() const { return m_data ? m_data->exists() : false; } bool Nepomuk::Resource::isValid() const { return m_data ? m_data->isValid() : false; } QString Nepomuk::Resource::genericLabel() const { QString label = this->label(); if ( label.isEmpty() ) { label = property( Soprano::Vocabulary::RDFS::label().toString() ).toString(); if ( label.isEmpty() ) { label = property( Soprano::Vocabulary::NAO::identifier().toString() ).toString(); if ( label.isEmpty() ) { label = property( Soprano::Vocabulary::Xesam::name().toString() ).toString(); if ( label.isEmpty() ) { label = property( Soprano::Vocabulary::Xesam::url().toString() ).toString().section( '/', -1 ); if ( label.isEmpty() ) { // ugly fallback label = resourceUri().toString(); } } } } } return label; } QString Nepomuk::Resource::genericDescription() const { QString s = property( Soprano::Vocabulary::NAO::description().toString() ).toString(); if ( !s.isEmpty() ) { return s; } s = property( Soprano::Vocabulary::Xesam::summary().toString() ).toString(); if ( !s.isEmpty() ) { return s; } s = property( Soprano::Vocabulary::Xesam::description().toString() ).toString(); if ( !s.isEmpty() ) { return s; } s = property( Soprano::Vocabulary::Xesam::asText().toString() ).toString(); if ( !s.isEmpty() ) { return s; } s = property( Soprano::Vocabulary::RDFS::comment().toString() ).toString(); return s; } QString Nepomuk::Resource::genericIcon() const { Variant symbol = property( Soprano::Vocabulary::NAO::hasSymbol().toString() ); if ( symbol.isString() ) { return symbol.toString(); } QString mimeType = property( Soprano::Vocabulary::Xesam::mimeType().toString() ).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(); } 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; } m_data->determineUri(); other.m_data->determineUri(); return resourceUri() == other.resourceUri(); } 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"); } } // do not remove, will be replaced with method definitions by the Nepomuk class generator QString Nepomuk::Resource::description() const { return ( property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#description" ).toStringList() << QString() ).first(); } void Nepomuk::Resource::setDescription( const QString& value ) { setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#description", Variant( value ) ); } QString Nepomuk::Resource::descriptionUri() { return "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#description"; } QStringList Nepomuk::Resource::identifiers() const { return property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#identifier" ).toStringList(); } void Nepomuk::Resource::setIdentifiers( const QStringList& value ) { setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#identifier", Variant( value ) ); } void Nepomuk::Resource::addIdentifier( const QString& value ) { Variant v = property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#identifier" ); v.append( value ); setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#identifier", v ); } QString Nepomuk::Resource::identifierUri() { return "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#identifier"; } QStringList Nepomuk::Resource::altLabels() const { return property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#altLabel" ).toStringList(); } void Nepomuk::Resource::setAltLabels( const QStringList& value ) { setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#altLabel", Variant( value ) ); } void Nepomuk::Resource::addAltLabel( const QString& value ) { Variant v = property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#altLabel" ); v.append( value ); setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#altLabel", v ); } QString Nepomuk::Resource::altLabelUri() { return "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#altLabel"; } QList 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( property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#annotation" ).toResourceList() ); } void Nepomuk::Resource::setAnnotations( const QList& value ) { setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/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( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#annotation" ); v.append( Resource( value ) ); setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#annotation", v ); } QString Nepomuk::Resource::annotationUri() { return "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#annotation"; } QList 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( property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag" ).toResourceList() ); } void Nepomuk::Resource::setTags( const QList& 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 l; for( QList::const_iterator it = value.constBegin(); it != value.constEnd(); ++it ) { l.append( Resource( (*it) ) ); } setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/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( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag" ); v.append( Resource( value ) ); setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag", v ); } QString Nepomuk::Resource::tagUri() { return "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTag"; } QList 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( property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTopic" ).toResourceList() ); } void Nepomuk::Resource::setTopics( const QList& value ) { setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/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( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTopic" ); v.append( Resource( value ) ); setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTopic", v ); } QString Nepomuk::Resource::topicUri() { return "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasTopic"; } QList 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( property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#isTopicOf" ).toResourceList() ); } void Nepomuk::Resource::setIsTopicOfs( const QList& value ) { setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/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( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#isTopicOf" ); v.append( Resource( value ) ); setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#isTopicOf", v ); } QString Nepomuk::Resource::isTopicOfUri() { return "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#isTopicOf"; } QList 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( property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#isRelated" ).toResourceList() ); } void Nepomuk::Resource::setIsRelateds( const QList& value ) { setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/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( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#isRelated" ); v.append( Resource( value ) ); setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#isRelated", v ); } QString Nepomuk::Resource::isRelatedUri() { return "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#isRelated"; } QString Nepomuk::Resource::label() const { return ( property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#label" ).toStringList() << QString() ).first(); } void Nepomuk::Resource::setLabel( const QString& value ) { setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#label", Variant( value ) ); } QString Nepomuk::Resource::labelUri() { return "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#label"; } quint32 Nepomuk::Resource::rating() const { return ( property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasRating" ).toUnsignedIntList() << 0 ).first(); } void Nepomuk::Resource::setRating( const quint32& value ) { setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasRating", Variant( value ) ); } QString Nepomuk::Resource::ratingUri() { return "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasRating"; } QStringList Nepomuk::Resource::symbols() const { return property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasSymbol" ).toStringList(); } void Nepomuk::Resource::setSymbols( const QStringList& value ) { setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasSymbol", Variant( value ) ); } void Nepomuk::Resource::addSymbol( const QString& value ) { Variant v = property( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasSymbol" ); v.append( value ); setProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasSymbol", v ); } QString Nepomuk::Resource::symbolUri() { return "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#hasSymbol"; } QList Nepomuk::Resource::annotationOf() const { return convertResourceList( ResourceManager::instance()->allResourcesWithProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#annotation", *this ) ); } QList Nepomuk::Resource::isRelatedOf() const { return convertResourceList( ResourceManager::instance()->allResourcesWithProperty( "http://www.semanticdesktop.org/ontologies/2007/08/15/nao#isRelated", *this ) ); } QList Nepomuk::Resource::allResources() { return Nepomuk::convertResourceList( ResourceManager::instance()->allResourcesOfType( "http://www.w3.org/2000/01/rdf-schema#Resource" ) ); } diff --git a/nepomuk/core/generated/resource.h b/nepomuk/core/generated/resource.h index f34cd95e5c..8fc236c884 100644 --- a/nepomuk/core/generated/resource.h +++ b/nepomuk/core/generated/resource.h @@ -1,575 +1,580 @@ /* * This file is part of the Nepomuk KDE project. * Copyright (C) 2006 Sebastian Trueg * * 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_H_ #define _NEPOMUK_RESOURCE_H_ #include #include #include #include "nepomuk_export.h" namespace Nepomuk { class ResourceData; class Variant; class Tag; class Resource; enum ErrorCode { NoError = 0, CommunicationError, /**< A commication error, i.e. connection failure */ InvalidType, UnknownError }; /** * \return A human-readble string. */ // FIXME: add the uri of the resource as parameter NEPOMUK_EXPORT QString errorString( ErrorCode code ); /** * \brief Resource is the central object type in Nepomuk. It represents a piece of * information of any kind. * * Resources are identified by their unique URI (which * correlates directly with the URI in the local NEPOMUK RDF storage. * * Resource objects with the same URI share their data. * * All methods in Resource are thread-safe. * * See \ref hacking for details on how to use Resource. * * \see ResourceManager */ class NEPOMUK_EXPORT Resource { public: /** - * Creates an empty invalid Resource + * Creates an empty invalid Resource. + * An invalid resource will become valid (i.e. get a new random URI) once setProperty + * is called. */ Resource(); Resource( const Resource& ); /** * Creates a new Resource object. * * The actual resource data is loaded on demand. Thus, it is possible to work * with Resources as if they were in memory all the time. * * \param uriOrIdentifier The unique URI or an arbitrary identifier of the resource. * If it exists as a resource URI in the RDF store it is used to load the * related properties. If not the passed string is treated * as an identifier. * If a resource exists in the store which has this identifier * set this resource's properties are loaded. Otherwise the * resource is created in the store * with a new random URI which can be accessed through \a uri * after the resource has been synced. The resource can later * again be found through the same identifier. * In Nepomuk there are two ways of identifying a resource * uniquely: * \li The URI of the resource which is generated randomly * by the framework and can only be accessed in a read-only * fashion. * \li An identifier in combination with the resource type (Be * aware that this identification can only be guranteed if identifiers * are never set manually via addIdentifier but only through the * constructor. * * \param type The URI identifying the type of the resource. If it is empty * Resource falls back to http://www.w3.org/2000/01/rdf-schema\#Resource or * in case the resource already exists the type will be read from the * store. (This is a QString instead of a QUrl for historical reasons) * * Example: * * The best way to understand the URI and identifier system is through file resources. * When a Resource object is created with the local path of the file as an identifier: * * \code * Resource myfile( "/tmp/testfile.txt" ); * \endcode * * Now the URI of the resource in the store representing metadata for the file /tmp/testfile.txt * is referred to by myfile.uri() which differs from the path of the file. However, the path of * the file is saved as a \a hasIdentifier relation which means that it can be used to easily find * the related resource. */ Resource( const QString& uriOrIdentifier, const QUrl& type = QUrl() ); /** * \deprecated use Resource( const QString&, const QUrl& ) */ KDE_DEPRECATED Resource( const QString& uriOrIdentifier, const QString& type ); /** * Creates a new Resource object. * * \param url The URI of the resource. If no resource with this URI exists, a new one is * created. * \param type The URI identifying the type of the resource. If it is empty * Resource falls back to http://www.w3.org/2000/01/rdf-schema\#Resource or * in case the resource already exists the type will be read from the * store. */ Resource( const QUrl& uri, const QUrl& type = QUrl() ); /** * Constructor used internally. */ Resource( ResourceData* ); virtual ~Resource(); Resource& operator=( const Resource& ); /** * The URI of the resource, uniquely identifying it. This URI in most * cases is a virtual one which has been created from a generic base * namespace and some identifier. * * the most important thing to remember is that the URI of for example * a file does not necessarily have a relation to its local path. * (Although Nepomuk tries to keep the URI of file resources in sync * with the file URL for convinience.) * * For historical reasons the method does return a URI as QString instead * of QUrl. The value equals resourceUri().toString(). * * \sa resourceUri, getIdentifiers * * \deprecated use resourceUri instead */ KDE_DEPRECATED QString uri() const; /** * The URI of the resource, uniquely identifying it. This URI in most * cases is a virtual one which has been created from a generic base * namespace and some identifier. * * the most important thing to remember is that the URI of for example * a file does not necessarily have a relation to its local path. * (Although Nepomuk tries to keep the URI of file resources in sync * with the file URL for convinience.) * * \sa uri, getIdentifiers */ QUrl resourceUri() const; /** * The main type of the resource. Nepomuk tries hard to make this * the type furthest down the hierarchy. In case the resource has only * one type, this is no problem. However, if the resource has multiple * types from different type hierarchies, there is no guarantee which * one will be used here. * * For historical reasons the method does return a URI as QString instead * of QUrl. The value equals resourceType().toString(). * * \sa name(), hasType(), types() * * \deprecated use resourceType instead */ KDE_DEPRECATED QString type() const; /** * The main type of the resource. Nepomuk tries hard to make this * the type furthest down the hierarchy. In case the resource has only * one type, this is no problem. However, if the resource has multiple * types from different type hierarchies, there is no guarantee which * one will be used here. * * \sa name(), hasType(), types() */ QUrl resourceType() const; /** * \return The list of all stored types for this resource. This may * also include types that lie in the same hierachy. * * \sa type(), hasType() */ QList types() const; /** * Check if the resource is of a certain type. The type hierarchy * is checked including subclass relations. */ bool hasType( const QUrl& typeUri ) const; /** * The name of the class this Resource represents an object of. * The classname is derived from the type URI (see Resource::uri). * For a translated user readable name of the resource see * Ontology::typeName. * * \sa type() */ QString className() const; /** * \return A list of all defined properties */ QHash allProperties() const; /** * Check if property identified by \a uri is defined * for this resource. * * \param uri The URI identifying the property. * * \return true if property \a uri has a value set. */ bool hasProperty( const QString& uri ) const; /** * Retrieve the value of property \a uri. If the property is not defined for * this resource an invalid, empty Variant object is returned. * * \param uri The URI identifying the property. */ Variant property( const QString& uri ) const; /** * Set a property of the resource. * * \param uri The URI identifying the property. * \param value The value of the property (i.e. the object of the RDF triple(s)) */ void setProperty( const QString& uri, const Variant& value ); /** * Remove property \a uri from this resource object. * * \param uri The URI identifying the property. */ void removeProperty( const QString& uri ); /** * Remove this resource completely. * CAUTION: After calling this method the resource will have been removed from the store * without any trace. */ void remove(); /** * \return true if this resource (i.e. the uri of this resource) exists in the local * NEPOMUK RDF store. */ bool exists() const; /** * \return true if this Resource object is valid, i.e. has a proper URI and type and * can be synced with the local NEPOMUK RDF store. + * + * An invalid resource will become valid (i.e. get a new random URI) once setProperty + * is called. */ bool isValid() const; /** * Tries very hard to find a suitable human-readable label for this resource. * It looks for properties such as nao:prefLabel, rdfs:label, or nao:identifier, * or even the fileName of File resources. * * \return A human readable label or if all fails the URI of the resource. */ QString genericLabel() const; /** * Tries very hard to find a suitable human-readable description of the resource. * This description is supposed to be longer than text() and includes such properties * as nao:description, xesam:comment, rdfs:comment * * \return A human readable description of the resource or an empty string if none * could be found. */ QString genericDescription() const; /** * Tries very hard to find an icon suitable for this resource. * * \return An icon name to be used with KIcon or an empty string if none was found. */ QString genericIcon() const; /** * Operator to compare two Resource objects. Normally one does not need this. It is * mainly intended for testing and debugging purposes. */ bool operator==( const Resource& ) const; /** * Get property 'description'. Everything can be annotated with * a simple string comment. */ QString description() const; /** * Set property 'description'. Everything can be annotated with * a simple string comment. */ void setDescription( const QString& value ); /** * \return The URI of the property 'description'. */ static QString descriptionUri(); /** * Get property 'identifier'. */ QStringList identifiers() const; /** * Set property 'identifier'. */ void setIdentifiers( const QStringList& value ); /** * Add a value to property 'identifier'. */ void addIdentifier( const QString& value ); /** * \return The URI of the property 'identifier'. */ static QString identifierUri(); /** * Get property 'altLabel'. */ QStringList altLabels() const; /** * Set property 'altLabel'. */ void setAltLabels( const QStringList& value ); /** * Add a value to property 'altLabel'. */ void addAltLabel( const QString& value ); /** * \return The URI of the property 'altLabel'. */ static QString altLabelUri(); /** * Get property 'annotation'. */ QList annotations() const; /** * Set property 'annotation'. */ void setAnnotations( const QList& value ); /** * Add a value to property 'annotation'. */ void addAnnotation( const Resource& value ); /** * \return The URI of the property 'annotation'. */ static QString annotationUri(); /** * Get property 'Tag'. Each Resource can be tagged with an arbitrary * number of Tags. This allows a simple grouping of resources. */ QList tags() const; /** * Set property 'Tag'. Each Resource can be tagged with an arbitrary * number of Tags. This allows a simple grouping of resources. */ void setTags( const QList& value ); /** * Add a value to property 'Tag'. Each Resource can be tagged with * an arbitrary number of Tags. This allows a simple grouping of * resources. */ void addTag( const Tag& value ); /** * \return The URI of the property 'Tag'. */ static QString tagUri(); /** * Get property 'Topic'. */ QList topics() const; /** * Set property 'Topic'. */ void setTopics( const QList& value ); /** * Add a value to property 'Topic'. */ void addTopic( const Resource& value ); /** * \return The URI of the property 'Topic'. */ static QString topicUri(); /** * Get property 'isTopicOf'. */ QList isTopicOfs() const; /** * Set property 'isTopicOf'. */ void setIsTopicOfs( const QList& value ); /** * Add a value to property 'isTopicOf'. */ void addIsTopicOf( const Resource& value ); /** * \return The URI of the property 'isTopicOf'. */ static QString isTopicOfUri(); /** * Get property 'isRelated'. */ QList isRelateds() const; /** * Set property 'isRelated'. */ void setIsRelateds( const QList& value ); /** * Add a value to property 'isRelated'. */ void addIsRelated( const Resource& value ); /** * \return The URI of the property 'isRelated'. */ static QString isRelatedUri(); /** * Get property 'label'. */ QString label() const; /** * Set property 'label'. */ void setLabel( const QString& value ); /** * \return The URI of the property 'label'. */ static QString labelUri(); /** * Get property 'Rating'. */ quint32 rating() const; /** * Set property 'Rating'. */ void setRating( const quint32& value ); /** * \return The URI of the property 'Rating'. */ static QString ratingUri(); /** * Get property 'Symbol'. Each resource can have a symbol assigned. * For now this is a simple string which can either be the patch to * an actual pixmap file or just the name of an icon as defined by * the freedesktop.org standard. */ QStringList symbols() const; /** * Set property 'Symbol'. Each resource can have a symbol assigned. * For now this is a simple string which can either be the patch to * an actual pixmap file or just the name of an icon as defined by * the freedesktop.org standard. */ void setSymbols( const QStringList& value ); /** * Add a value to property 'Symbol'. Each resource can have a symbol * assigned. For now this is a simple string which can either be * the patch to an actual pixmap file or just the name of an icon as * defined by the freedesktop.org standard. */ void addSymbol( const QString& value ); /** * \return The URI of the property 'Symbol'. */ static QString symbolUri(); /** * Get all resources that have this resource set as property 'annotation'. * \sa ResourceManager::allResourcesWithProperty */ QList annotationOf() const; /** * Get all resources that have this resource set as property 'isRelated'. * \sa ResourceManager::allResourcesWithProperty */ QList isRelatedOf() const; /** * Retrieve a list of all available Resource resources. This list * consists of all resource of type Resource that are stored in * the local Nepomuk meta data storage and any changes made locally. * Be aware that in some cases this list can get very big. Then it * might be better to use libKNep directly. */ static QList allResources(); private: ResourceData* m_data; class Private; Private* d; // unused friend class ResourceData; }; } #endif diff --git a/nepomuk/core/resource.cpp.in b/nepomuk/core/resource.cpp.in index 23b6da434b..8b802a1ec0 100644 --- a/nepomuk/core/resource.cpp.in +++ b/nepomuk/core/resource.cpp.in @@ -1,343 +1,343 @@ /* * This file is part of the Nepomuk KDE project. * Copyright (C) 2006 Sebastian Trueg * * 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 "tools.h" #include #include #include #include #include #include // FIXME: let the code generator do this #include "tag.h" Nepomuk::Resource::Resource() - : m_data( 0 ) { + m_data = ResourceData::data( QUrl(), QUrl() ); } Nepomuk::Resource::Resource( const Nepomuk::Resource& res ) { m_data = res.m_data; if ( m_data ) m_data->ref(); } Nepomuk::Resource::Resource( const QString& uri, const QUrl& type ) { m_data = ResourceData::data( uri, type ); if ( m_data ) m_data->ref(); } Nepomuk::Resource::Resource( const QString& uri, const QString& type ) { m_data = ResourceData::data( uri, type ); if ( m_data ) m_data->ref(); } Nepomuk::Resource::Resource( const QUrl& uri, const QUrl& type ) { m_data = ResourceData::data( uri, type ); if ( m_data ) m_data->ref(); } Nepomuk::Resource::Resource( Nepomuk::ResourceData* data ) { m_data = data; if ( m_data ) data->ref(); } Nepomuk::Resource::~Resource() { if( m_data && m_data->deref() == 0 ) { // m_data->deleteData(); } } Nepomuk::Resource& Nepomuk::Resource::operator=( const Resource& res ) { if( m_data != res.m_data ) { if ( m_data && m_data->deref() == 0 ) { // m_data->deleteData(); } m_data = res.m_data; if ( m_data ) m_data->ref(); } return *this; } QString Nepomuk::Resource::uri() const { return resourceUri().toString(); } QUrl Nepomuk::Resource::resourceUri() const { if ( m_data ) { m_data->determineUri(); return m_data->uri(); } else { return QUrl(); } } QString Nepomuk::Resource::type() const { return resourceType().toString(); } QUrl Nepomuk::Resource::resourceType() const { if ( m_data ) { return m_data->type(); } else { return QUrl(); } } QList Nepomuk::Resource::types() const { if ( m_data ) { return m_data->allTypes(); } else { return QList(); } } bool Nepomuk::Resource::hasType( const QUrl& typeUri ) const { return m_data ? m_data->hasType( typeUri ) : false; } QString Nepomuk::Resource::className() const { return resourceType().toString().section( QRegExp( "[#:]" ), -1 ); } QHash Nepomuk::Resource::allProperties() const { if ( m_data ) { return m_data->allProperties(); } else { return QHash(); } } bool Nepomuk::Resource::hasProperty( const QString& uri ) const { return m_data ? m_data->hasProperty( uri ) : false; } Nepomuk::Variant Nepomuk::Resource::property( const QString& uri ) const { if ( m_data ) { return m_data->property( uri ); } else { return Variant(); } } void Nepomuk::Resource::setProperty( const QString& uri, const Nepomuk::Variant& value ) { if ( m_data ) { m_data->setProperty( uri, value ); } } void Nepomuk::Resource::removeProperty( const QString& uri ) { if ( m_data ) { m_data->removeProperty( uri ); } } void Nepomuk::Resource::remove() { if ( m_data ) { m_data->remove(); } } bool Nepomuk::Resource::exists() const { return m_data ? m_data->exists() : false; } bool Nepomuk::Resource::isValid() const { return m_data ? m_data->isValid() : false; } QString Nepomuk::Resource::genericLabel() const { QString label = this->label(); if ( label.isEmpty() ) { label = property( Soprano::Vocabulary::RDFS::label().toString() ).toString(); if ( label.isEmpty() ) { label = property( Soprano::Vocabulary::NAO::identifier().toString() ).toString(); if ( label.isEmpty() ) { label = property( Soprano::Vocabulary::Xesam::name().toString() ).toString(); if ( label.isEmpty() ) { label = property( Soprano::Vocabulary::Xesam::url().toString() ).toString().section( '/', -1 ); if ( label.isEmpty() ) { // ugly fallback label = resourceUri().toString(); } } } } } return label; } QString Nepomuk::Resource::genericDescription() const { QString s = property( Soprano::Vocabulary::NAO::description().toString() ).toString(); if ( !s.isEmpty() ) { return s; } s = property( Soprano::Vocabulary::Xesam::summary().toString() ).toString(); if ( !s.isEmpty() ) { return s; } s = property( Soprano::Vocabulary::Xesam::description().toString() ).toString(); if ( !s.isEmpty() ) { return s; } s = property( Soprano::Vocabulary::Xesam::asText().toString() ).toString(); if ( !s.isEmpty() ) { return s; } s = property( Soprano::Vocabulary::RDFS::comment().toString() ).toString(); return s; } QString Nepomuk::Resource::genericIcon() const { Variant symbol = property( Soprano::Vocabulary::NAO::hasSymbol().toString() ); if ( symbol.isString() ) { return symbol.toString(); } QString mimeType = property( Soprano::Vocabulary::Xesam::mimeType().toString() ).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(); } 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; } m_data->determineUri(); other.m_data->determineUri(); return resourceUri() == other.resourceUri(); } 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"); } } // do not remove, will be replaced with method definitions by the Nepomuk class generator NEPOMUK_METHODS diff --git a/nepomuk/core/resource.h.in b/nepomuk/core/resource.h.in index 5af620b26b..1bd342e5c4 100644 --- a/nepomuk/core/resource.h.in +++ b/nepomuk/core/resource.h.in @@ -1,336 +1,341 @@ /* * This file is part of the Nepomuk KDE project. * Copyright (C) 2006 Sebastian Trueg * * 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_H_ #define _NEPOMUK_RESOURCE_H_ #include #include #include #include "nepomuk_export.h" namespace Nepomuk { class ResourceData; class Variant; // do not remove. Will be replaced with class declarations by the Nepomuk class generator. NEPOMUK_OTHERCLASSES enum ErrorCode { NoError = 0, CommunicationError, /**< A commication error, i.e. connection failure */ InvalidType, UnknownError }; /** * \return A human-readble string. */ // FIXME: add the uri of the resource as parameter NEPOMUK_EXPORT QString errorString( ErrorCode code ); /** * \brief Resource is the central object type in Nepomuk. It represents a piece of * information of any kind. * * Resources are identified by their unique URI (which * correlates directly with the URI in the local NEPOMUK RDF storage. * * Resource objects with the same URI share their data. * * All methods in Resource are thread-safe. * * See \ref hacking for details on how to use Resource. * * \see ResourceManager */ class NEPOMUK_EXPORT Resource { public: /** - * Creates an empty invalid Resource + * Creates an empty invalid Resource. + * An invalid resource will become valid (i.e. get a new random URI) once setProperty + * is called. */ Resource(); Resource( const Resource& ); /** * Creates a new Resource object. * * The actual resource data is loaded on demand. Thus, it is possible to work * with Resources as if they were in memory all the time. * * \param uriOrIdentifier The unique URI or an arbitrary identifier of the resource. * If it exists as a resource URI in the RDF store it is used to load the * related properties. If not the passed string is treated * as an identifier. * If a resource exists in the store which has this identifier * set this resource's properties are loaded. Otherwise the * resource is created in the store * with a new random URI which can be accessed through \a uri * after the resource has been synced. The resource can later * again be found through the same identifier. * In Nepomuk there are two ways of identifying a resource * uniquely: * \li The URI of the resource which is generated randomly * by the framework and can only be accessed in a read-only * fashion. * \li An identifier in combination with the resource type (Be * aware that this identification can only be guranteed if identifiers * are never set manually via addIdentifier but only through the * constructor. * * \param type The URI identifying the type of the resource. If it is empty * Resource falls back to http://www.w3.org/2000/01/rdf-schema\#Resource or * in case the resource already exists the type will be read from the * store. (This is a QString instead of a QUrl for historical reasons) * * Example: * * The best way to understand the URI and identifier system is through file resources. * When a Resource object is created with the local path of the file as an identifier: * * \code * Resource myfile( "/tmp/testfile.txt" ); * \endcode * * Now the URI of the resource in the store representing metadata for the file /tmp/testfile.txt * is referred to by myfile.uri() which differs from the path of the file. However, the path of * the file is saved as a \a hasIdentifier relation which means that it can be used to easily find * the related resource. */ Resource( const QString& uriOrIdentifier, const QUrl& type = QUrl() ); /** * \deprecated use Resource( const QString&, const QUrl& ) */ KDE_DEPRECATED Resource( const QString& uriOrIdentifier, const QString& type ); /** * Creates a new Resource object. * * \param url The URI of the resource. If no resource with this URI exists, a new one is * created. * \param type The URI identifying the type of the resource. If it is empty * Resource falls back to http://www.w3.org/2000/01/rdf-schema\#Resource or * in case the resource already exists the type will be read from the * store. */ Resource( const QUrl& uri, const QUrl& type = QUrl() ); /** * Constructor used internally. */ Resource( ResourceData* ); virtual ~Resource(); Resource& operator=( const Resource& ); /** * The URI of the resource, uniquely identifying it. This URI in most * cases is a virtual one which has been created from a generic base * namespace and some identifier. * * the most important thing to remember is that the URI of for example * a file does not necessarily have a relation to its local path. * (Although Nepomuk tries to keep the URI of file resources in sync * with the file URL for convinience.) * * For historical reasons the method does return a URI as QString instead * of QUrl. The value equals resourceUri().toString(). * * \sa resourceUri, getIdentifiers * * \deprecated use resourceUri instead */ KDE_DEPRECATED QString uri() const; /** * The URI of the resource, uniquely identifying it. This URI in most * cases is a virtual one which has been created from a generic base * namespace and some identifier. * * the most important thing to remember is that the URI of for example * a file does not necessarily have a relation to its local path. * (Although Nepomuk tries to keep the URI of file resources in sync * with the file URL for convinience.) * * \sa uri, getIdentifiers */ QUrl resourceUri() const; /** * The main type of the resource. Nepomuk tries hard to make this * the type furthest down the hierarchy. In case the resource has only * one type, this is no problem. However, if the resource has multiple * types from different type hierarchies, there is no guarantee which * one will be used here. * * For historical reasons the method does return a URI as QString instead * of QUrl. The value equals resourceType().toString(). * * \sa name(), hasType(), types() * * \deprecated use resourceType instead */ KDE_DEPRECATED QString type() const; /** * The main type of the resource. Nepomuk tries hard to make this * the type furthest down the hierarchy. In case the resource has only * one type, this is no problem. However, if the resource has multiple * types from different type hierarchies, there is no guarantee which * one will be used here. * * \sa name(), hasType(), types() */ QUrl resourceType() const; /** * \return The list of all stored types for this resource. This may * also include types that lie in the same hierachy. * * \sa type(), hasType() */ QList types() const; /** * Check if the resource is of a certain type. The type hierarchy * is checked including subclass relations. */ bool hasType( const QUrl& typeUri ) const; /** * The name of the class this Resource represents an object of. * The classname is derived from the type URI (see Resource::uri). * For a translated user readable name of the resource see * Ontology::typeName. * * \sa type() */ QString className() const; /** * \return A list of all defined properties */ QHash allProperties() const; /** * Check if property identified by \a uri is defined * for this resource. * * \param uri The URI identifying the property. * * \return true if property \a uri has a value set. */ bool hasProperty( const QString& uri ) const; /** * Retrieve the value of property \a uri. If the property is not defined for * this resource an invalid, empty Variant object is returned. * * \param uri The URI identifying the property. */ Variant property( const QString& uri ) const; /** * Set a property of the resource. * * \param uri The URI identifying the property. * \param value The value of the property (i.e. the object of the RDF triple(s)) */ void setProperty( const QString& uri, const Variant& value ); /** * Remove property \a uri from this resource object. * * \param uri The URI identifying the property. */ void removeProperty( const QString& uri ); /** * Remove this resource completely. * CAUTION: After calling this method the resource will have been removed from the store * without any trace. */ void remove(); /** * \return true if this resource (i.e. the uri of this resource) exists in the local * NEPOMUK RDF store. */ bool exists() const; /** * \return true if this Resource object is valid, i.e. has a proper URI and type and * can be synced with the local NEPOMUK RDF store. + * + * An invalid resource will become valid (i.e. get a new random URI) once setProperty + * is called. */ bool isValid() const; /** * Tries very hard to find a suitable human-readable label for this resource. * It looks for properties such as nao:prefLabel, rdfs:label, or nao:identifier, * or even the fileName of File resources. * * \return A human readable label or if all fails the URI of the resource. */ QString genericLabel() const; /** * Tries very hard to find a suitable human-readable description of the resource. * This description is supposed to be longer than text() and includes such properties * as nao:description, xesam:comment, rdfs:comment * * \return A human readable description of the resource or an empty string if none * could be found. */ QString genericDescription() const; /** * Tries very hard to find an icon suitable for this resource. * * \return An icon name to be used with KIcon or an empty string if none was found. */ QString genericIcon() const; /** * Operator to compare two Resource objects. Normally one does not need this. It is * mainly intended for testing and debugging purposes. */ bool operator==( const Resource& ) const; // do not remove. Will be replaced with method declarations by the Nepomuk class generator. NEPOMUK_METHODS private: ResourceData* m_data; class Private; Private* d; // unused friend class ResourceData; }; } #endif diff --git a/nepomuk/core/resourcedata.cpp b/nepomuk/core/resourcedata.cpp index 358e7cc24d..ea7a385af2 100644 --- a/nepomuk/core/resourcedata.cpp +++ b/nepomuk/core/resourcedata.cpp @@ -1,771 +1,779 @@ /* * This file is part of the Nepomuk KDE project. * Copyright (C) 2006-2007 Sebastian Trueg * * 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 "generated/resource.h" #include "tools.h" #include "resourcefiltermodel.h" #include #include #include #include #include #include #include "ontology/class.h" #include #include #include using namespace Soprano; static inline uint qHash( const QUrl& url ) { return qHash( url.toString() ); } typedef QHash ResourceDataHash; // FIXME: make these things thread-safe. Even better: put them into the ResourceManager and make that thread-safe! Q_GLOBAL_STATIC( ResourceDataHash, initializedData ) Q_GLOBAL_STATIC( ResourceDataHash, kickoffData ) static int s_dataCnt = 0; static Nepomuk::Variant nodeToVariant( const Soprano::Node& node ) { if ( node.isResource() ) { return Nepomuk::Variant( Nepomuk::Resource( node.uri() ) ); } else if ( node.isLiteral() ) { return Nepomuk::Variant( node.literal().variant() ); } else { return Nepomuk::Variant(); } } Nepomuk::ResourceData::ResourceData( const QUrl& uri, const QString& uriOrId, const QUrl& type ) : m_kickoffUriOrId( uriOrId ), m_uri( uri ), m_mainType( type ), m_ref(0), m_proxyData(0), m_cacheDirty(true) { - if( m_mainType.isEmpty() && !( uriOrId.isEmpty() && uri.isEmpty() ) ) + if( m_mainType.isEmpty() ) m_mainType = Soprano::Vocabulary::RDFS::Resource(); m_types << m_mainType; // TODO: handle the caching in a decent Cache class and not this ugly. if ( s_dataCnt >= 1000 ) { for( ResourceDataHash::iterator rdIt = initializedData()->begin(); rdIt != initializedData()->end(); ++rdIt ) { ResourceData* data = rdIt.value(); if ( !data->cnt() ) { data->deleteData(); break; } } } ++s_dataCnt; } Nepomuk::ResourceData::~ResourceData() { --s_dataCnt; if( m_proxyData ) m_proxyData->deref(); } QString Nepomuk::ResourceData::kickoffUriOrId() const { if( m_proxyData ) return m_proxyData->kickoffUriOrId(); return m_kickoffUriOrId; } QUrl Nepomuk::ResourceData::uri() const { if( m_proxyData ) return m_proxyData->uri(); return m_uri; } QUrl Nepomuk::ResourceData::type() { if( m_proxyData ) return m_proxyData->type(); load(); return m_mainType; } QList Nepomuk::ResourceData::allTypes() { if( m_proxyData ) return m_proxyData->allTypes(); load(); return m_types; } void Nepomuk::ResourceData::deleteData() { if( m_proxyData ) if( m_proxyData->deref() ) m_proxyData->deleteData(); m_proxyData = 0; if( !m_uri.isEmpty() ) initializedData()->remove( m_uri.toString() ); if( !m_kickoffUriOrId.isEmpty() ) kickoffData()->remove( m_kickoffUriOrId ); deleteLater(); } QHash Nepomuk::ResourceData::allProperties() { if( m_proxyData ) return m_proxyData->allProperties(); Soprano::Model* model = ResourceManager::instance()->mainModel(); QHash props; if ( determineUri() ) { Soprano::StatementIterator it = model->listStatements( Soprano::Statement( m_uri, Soprano::Node(), Soprano::Node() ) ); while ( it.next() ) { Statement statement = *it; if ( props.contains( statement.predicate().toString() ) ) { props[statement.predicate().toString()].append( nodeToVariant( statement.object() ) ); } else { props.insert( statement.predicate().toString(), nodeToVariant( statement.object() ) ); } } it.close(); } return props; } bool Nepomuk::ResourceData::hasProperty( const QString& uri ) { if( m_proxyData ) return m_proxyData->hasProperty( uri ); if ( determineUri() ) { return ResourceManager::instance()->mainModel()->containsAnyStatement( Soprano::Statement( m_uri, QUrl( uri ), Soprano::Node() ) ); } else { return false; } } bool Nepomuk::ResourceData::hasType( const QUrl& uri ) { if( m_proxyData ) return m_proxyData->hasType( uri ); if ( load() ) { Types::Class requestedType( uri ); for ( QList::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 QString& uri ) { if( m_proxyData ) return m_proxyData->property( uri ); if ( load() ) { QHash::iterator it = m_cache.find( uri ); if ( it == m_cache.end() ) { return Variant(); } else { return *it; } } else { return Variant(); } // Variant v; // if ( determineUri() ) { // Soprano::Model* model = ResourceManager::instance()->mainModel(); // Soprano::StatementIterator it = model->listStatements( Soprano::Statement( m_uri, QUrl(uri), Soprano::Node() ) ); // while ( it.next() ) { // Statement statement = *it; // v.append( nodeToVariant( statement.object() ) ); // } // it.close(); // } // return v; } bool Nepomuk::ResourceData::store() { if ( determineUri() ) { if ( !exists() ) { QList statements; // save type (There should be no need to save all the types since there is only one way // that m_types contains more than one element: if we loaded them) statements.append( Statement( m_uri, Soprano::Vocabulary::RDF::type(), m_types.first() ) ); // save the kickoff identifier (other identifiers are stored via setProperty) if ( !m_kickoffIdentifier.isEmpty() ) { statements.append( Statement( m_uri, QUrl(Resource::identifierUri()), LiteralValue(m_kickoffIdentifier) ) ); } // HACK: make sure that files have proper fileUrl properties so long as we do not have a File class for // Dolphin and co. if ( QFile::exists( m_uri.toLocalFile())) { statements.append( Statement( m_uri, Soprano::Vocabulary::Xesam::url(), LiteralValue( m_uri.toLocalFile() ) ) ); } ResourceFilterModel fm( ResourceManager::instance()->mainModel() ); return fm.addStatements( statements ) == Soprano::Error::ErrorNone; } else { return true; } } else { return false; } } bool Nepomuk::ResourceData::load() { if ( m_cacheDirty ) { m_cache.clear(); if ( determineUri() ) { Soprano::Model* model = ResourceManager::instance()->mainModel(); Soprano::StatementIterator it = model->listStatements( Soprano::Statement( m_uri, Soprano::Node(), Soprano::Node() ) ); while ( it.next() ) { Statement statement = *it; if ( statement.predicate().uri() == Soprano::Vocabulary::RDF::type() ) { if ( statement.object().isResource() ) { QUrl storedType = statement.object().uri(); 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 { m_cache[statement.predicate().uri()].append( nodeToVariant( statement.object() ) ); } } m_cacheDirty = false; return true; } else { return false; } } else { return true; } } void Nepomuk::ResourceData::setProperty( const QString& uri, const Nepomuk::Variant& value ) { if( m_proxyData ) return m_proxyData->setProperty( uri, value ); // step 0: make sure this resource is in the store if ( store() ) { QList valueNodes; // make sure resource values are in the store if ( value.simpleType() == qMetaTypeId() ) { QList l = value.toResourceList(); for( QList::iterator resIt = l.begin(); resIt != l.end(); ++resIt ) { if ( resIt->isValid() ) resIt->m_data->store(); } } // add the actual property statements // one-to-one Resource if( value.isResource() ) { valueNodes.append( value.toResource().resourceUri() ); } // one-to-many Resource else if( value.isResourceList() ) { const QList& l = value.toResourceList(); for( QList::const_iterator resIt = l.constBegin(); resIt != l.constEnd(); ++resIt ) { valueNodes.append( (*resIt).resourceUri() ); } } // one-to-many literals else if( value.isList() ) { valueNodes += Nepomuk::valuesToRDFNodes( value ); } // one-to-one literal else { valueNodes.append( Nepomuk::valueToRDFNode( value ) ); } // update the cache for now m_cache[uri] = value; // update the store ResourceFilterModel fm( ResourceManager::instance()->mainModel() ); fm.updateProperty( m_uri, QUrl(uri), valueNodes ); } } void Nepomuk::ResourceData::removeProperty( const QString& uri ) { if( m_proxyData ) return m_proxyData->removeProperty( uri ); if ( determineUri() ) { ResourceFilterModel fm( ResourceManager::instance()->mainModel() ); fm.removeProperty( m_uri, QUrl(uri) ); } } void Nepomuk::ResourceData::remove( bool recursive ) { if( m_proxyData ) return m_proxyData->remove(); if ( determineUri() ) { // FIXME: make sure no dangling graphs are left ResourceFilterModel fm( ResourceManager::instance()->mainModel() ); fm.removeAllStatements( Statement( m_uri, Node(), Node() ) ); if ( recursive ) { fm.removeAllStatements( Statement( Node(), Node(), m_uri ) ); } } } bool Nepomuk::ResourceData::exists() { if( m_proxyData ) return m_proxyData->exists(); if( determineUri() ) { return ResourceManager::instance()->mainModel()->containsAnyStatement( Statement( m_uri, Node(), Node() ) ); } else return false; } bool Nepomuk::ResourceData::isValid() const { if( m_proxyData ) return m_proxyData->isValid(); // FIXME: check namespaces and stuff - return( !m_mainType.isEmpty() ); + return( !m_mainType.isEmpty() && ( !m_uri.isEmpty() || !m_kickoffIdentifier.isEmpty() ) ); } bool Nepomuk::ResourceData::determineUri() { if( m_proxyData ) return m_proxyData->determineUri(); - if( m_uri.isEmpty() ) { + if ( m_uri.isEmpty() && m_kickoffIdentifier.isEmpty() ) { + // create a random URI and add us to the initialized data, i.e. make us "valid" + m_modificationMutex.lock(); + m_uri = ResourceManager::instance()->generateUniqueUri(); + initializedData()->insert( m_uri.toString(), this ); + m_modificationMutex.unlock(); + } + + else if( m_uri.isEmpty() ) { Q_ASSERT( !m_kickoffUriOrId.isEmpty() ); m_modificationMutex.lock(); Soprano::Model* model = ResourceManager::instance()->mainModel(); if( model->containsAnyStatement( Statement( QUrl( kickoffUriOrId() ), Node(), Node() ) ) ) { // // The kickoffUriOrId is actually a URI // m_uri = kickoffUriOrId(); kDebug(300004) << " kickoff identifier " << kickoffUriOrId() << " exists as a URI " << uri(); } else { // // Check if the kickoffUriOrId is a resource identifier // StatementIterator it = model->listStatements( Statement( Node(), Node(QUrl( Resource::identifierUri() )), LiteralValue( kickoffUriOrId() ) ) ); // // The kickoffUriOrId is an identifier // // Identifiers are not unique! // Thus, we do the following: // - If we have Ontology support, i.e. we know the classes: // We reuse a resource if its type is derived from the // current type of the other way around (example: an ImageFile // is a File and if we open an ImageFile as File we do want it to // keep its ImageFile type) // - If we do not have Ontology support: // Fallback to the default behaviour of always reusing existing // data. // // TODO: basically it is perfectly valid to store both types in the first case // Q_ASSERT( !m_mainType.isEmpty() ); if ( it.next() ) { // At this point we only have one type since without a uri we could not have loaded other types // than the one used on construction Types::Class wantedType( m_mainType ); if ( m_mainType != Soprano::Vocabulary::RDFS::Resource() && wantedType.isAvailable() ) { do { // get the type of the stored resource StatementIterator resourceSl = model->listStatements( Statement( it.current().subject(), Soprano::Vocabulary::RDF::type(), Node() ) ); while ( resourceSl.next() ) { if ( resourceSl.current().object().isResource() ) { Types::Class storedType = resourceSl.current().object().uri(); if ( storedType == wantedType || wantedType.isSubClassOf( storedType ) || storedType.isSubClassOf( wantedType ) ) { // in load() The type will be updated properly m_uri = it.current().subject().uri(); break; } } } } while ( it.next() && m_uri.isEmpty() ); } else { m_uri = it.current().subject().uri(); kDebug(300004) << k_funcinfo << " kickoff identifier " << kickoffUriOrId() << " already exists with URI " << uri(); } } it.close(); if ( m_uri.isEmpty() ) { // // The resource does not exist, create a new one: // If the kickoffUriOrId is a valid URI we use it as such, otherwise we create a new URI // Special case: files: paths are always converted to URIs // QUrl uri( kickoffUriOrId() ); if ( uri.isValid() && !uri.scheme().isEmpty() ) { m_uri = uri; } else if ( QFile::exists( kickoffUriOrId() ) ) { // KURL defaults to schema "file:" m_uri = KUrl::fromPath( kickoffUriOrId() ); } else { m_kickoffIdentifier = kickoffUriOrId(); m_uri = ResourceManager::instance()->generateUniqueUri(); } kDebug(300004) << " kickoff identifier " << kickoffUriOrId() << " seems fresh. Generated new URI " << m_uri; } } // // Move us to the final data hash now that the URI is known // if( !uri().isEmpty() && uri() != kickoffUriOrId() ) { if( !initializedData()->contains( uri().toString() ) ) initializedData()->insert( uri().toString(), this ); else { m_proxyData = initializedData()->value( uri().toString() ); m_proxyData->ref(); } } m_modificationMutex.unlock(); } return !m_uri.isEmpty(); } // void Nepomuk::ResourceData::updateType() // { // Soprano::Model* model = ResourceManager::instance()->mainModel(); // // get the type of the stored resource // StatementIterator typeStatements = model->listStatements( Statement( m_uri, // Soprano::Vocabulary::RDF::type(), // Node() ) ); // if ( typeStatements.next() && typeStatements.current().object().isResource() ) { // // FIXME: handle multple types, maybe select the one type that fits best // QUrl storedType = typeStatements.current().object().uri(); // if ( m_type == Soprano::Vocabulary::RDFS::Resource() ) { // Q_ASSERT( !storedType.isEmpty() ); // m_type = storedType; // } // else { // Types::Class wantedTypeClass = m_type; // Types::Class storedTypeClass = storedType; // // Keep the type that is further down the hierarchy // if ( wantedTypeClass.isSubClassOf( storedTypeClass ) ) { // m_type = wantedTypeClass.uri(); // } // } // } // } bool Nepomuk::ResourceData::operator==( const ResourceData& other ) const { const ResourceData* that = this; if( m_proxyData ) that = m_proxyData; if( that == &other ) return true; if( that->m_uri != other.m_uri || that->m_mainType != other.m_mainType ) { kDebug(300004) << "different uri or type"; return false; } return true; } Nepomuk::ResourceData* Nepomuk::ResourceData::data( const QUrl& uri, const QUrl& type ) { if ( uri.isEmpty() ) { - return 0; + return new ResourceData( uri, QString(), type ); } // default to "file" scheme, i.e. we do not allow an empty scheme if ( uri.scheme().isEmpty() ) { QUrl fileUri( uri ); fileUri.setScheme( "file" ); return data( fileUri, type ); } ResourceDataHash::iterator it = initializedData()->find( uri.toString() ); // // The uriOrId has no local representation yet -> create one // if( it == initializedData()->end() ) { kDebug(300004) << "No existing ResourceData instance found for uri " << uri; // // The actual URI is already known here // ResourceData* d = new ResourceData( uri, QString(), type ); initializedData()->insert( uri.toString(), d ); return d; } else { // // Reuse the already existing ResourceData object // return it.value(); } } Nepomuk::ResourceData* Nepomuk::ResourceData::data( const QString& uriOrId, const QUrl& type ) { if ( uriOrId.isEmpty() ) { - return 0; + return new ResourceData( QUrl(), QString(), type ); } // special case: files (only absolute paths for now) if ( uriOrId[0] == '/' ) { ResourceDataHash::iterator it = initializedData()->find( "file://" + uriOrId ); if ( it != initializedData()->end() ) { return *it; } } ResourceDataHash::iterator it = initializedData()->find( uriOrId ); bool resFound = ( it != initializedData()->end() ); // // The uriOrId is not a known local URI. Might be a kickoff value though // if( it == initializedData()->end() ) { it = kickoffData()->find( uriOrId ); // check if the type matches (see determineUri for details) if ( !type.isEmpty() && type != Soprano::Vocabulary::RDFS::Resource() ) { Types::Class wantedType = type; while ( it != kickoffData()->end() && it.key() == uriOrId ) { if ( it.value()->hasType( type ) ) { break; } ++it; } } resFound = ( it != kickoffData()->end() && it.key() == uriOrId ); } // // The uriOrId has no local representation yet -> create one // if( !resFound ) { kDebug(300004) << "No existing ResourceData instance found for uriOrId " << uriOrId; // // Every new ResourceData object ends up in the kickoffdata since its actual URI is not known yet // ResourceData* d = new ResourceData( QUrl(), uriOrId, type ); kickoffData()->insert( uriOrId, d ); return d; } else { // // Reuse the already existing ResourceData object // return it.value(); } } QList Nepomuk::ResourceData::allResourceDataOfType( const QString& type ) { QList l; if( !type.isEmpty() ) { for( ResourceDataHash::iterator rdIt = kickoffData()->begin(); rdIt != kickoffData()->end(); ++rdIt ) { if( rdIt.value()->type() == type ) { l.append( rdIt.value() ); } } } return l; } QList Nepomuk::ResourceData::allResourceDataWithProperty( const QString& _uri, const Variant& v ) { QList l; for( ResourceDataHash::iterator rdIt = kickoffData()->begin(); rdIt != kickoffData()->end(); ++rdIt ) { if( rdIt.value()->hasProperty( _uri ) && rdIt.value()->property( _uri ) == v ) { l.append( rdIt.value() ); } } return l; } QList Nepomuk::ResourceData::allResourceData() { QList l; for( ResourceDataHash::iterator rdIt = kickoffData()->begin(); rdIt != kickoffData()->end(); ++rdIt ) { l.append( rdIt.value() ); } for( ResourceDataHash::iterator rdIt = initializedData()->begin(); rdIt != initializedData()->end(); ++rdIt ) { l.append( rdIt.value() ); } return l; } #include "resourcedata.moc"