• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • Sitemap
  • Contact Us
 

akonadi

entitycache_p.h

00001 /*
00002     Copyright (c) 2009 Volker Krause <vkrause@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #ifndef AKONADI_ENTITYCACHE_P_H
00021 #define AKONADI_ENTITYCACHE_P_H
00022 
00023 #include <akonadi/item.h>
00024 #include <akonadi/itemfetchjob.h>
00025 #include <akonadi/itemfetchscope.h>
00026 #include <akonadi/collection.h>
00027 #include <akonadi/collectionfetchjob.h>
00028 #include <akonadi/collectionfetchscope.h>
00029 #include <akonadi/session.h>
00030 
00031 #include <qobject.h>
00032 #include <QQueue>
00033 #include <QVariant>
00034 #include <QtCore/QQueue>
00035 
00036 class KJob;
00037 
00038 namespace Akonadi {
00039 
00044 class EntityCacheBase : public QObject
00045 {
00046   Q_OBJECT
00047   public:
00048     explicit EntityCacheBase ( Session *session, QObject * parent = 0 );
00049 
00050     void setSession(Session *session);
00051 
00052   protected:
00053     Session *session;
00054 
00055   signals:
00056     void dataAvailable();
00057 
00058   private slots:
00059     virtual void fetchResult( KJob* job ) = 0;
00060 };
00061 
00062 template <typename T>
00063 struct EntityCacheNode
00064 {
00065   EntityCacheNode() : pending( false ), invalid( false ) {}
00066   EntityCacheNode( typename T::Id id ) : entity( T( id ) ), pending( true ), invalid( false ) {}
00067   T entity;
00068   bool pending;
00069   bool invalid;
00070 };
00071 
00076 template<typename T, typename FetchJob, typename FetchScope>
00077 class EntityCache : public EntityCacheBase
00078 {
00079   public:
00080     explicit EntityCache( int maxCapacity, Session *session = 0, QObject *parent = 0 ) :
00081       EntityCacheBase( session, parent ),
00082       mCapacity( maxCapacity )
00083     {}
00084 
00085     ~EntityCache()
00086     {
00087       qDeleteAll( mCache );
00088     }
00089 
00091     bool isCached( typename T::Id id ) const
00092     {
00093       EntityCacheNode<T>* node = cacheNodeForId( id );
00094       return node && !node->pending;
00095     }
00096 
00098     bool isRequested( typename T::Id id ) const
00099     {
00100       return cacheNodeForId( id );
00101     }
00102 
00104     T retrieve( typename T::Id id ) const
00105     {
00106       EntityCacheNode<T>* node = cacheNodeForId( id );
00107       if ( node && !node->pending && !node->invalid )
00108         return node->entity;
00109       return T();
00110     }
00111 
00113     void invalidate( typename T::Id id )
00114     {
00115       EntityCacheNode<T>* node = cacheNodeForId( id );
00116       if ( node )
00117         node->invalid = true;
00118     }
00119 
00121     void update( typename T::Id id, const FetchScope &scope )
00122     {
00123       EntityCacheNode<T>* node = cacheNodeForId( id );
00124       if ( node ) {
00125         mCache.removeAll( node );
00126         if ( node->pending )
00127           request( id, scope );
00128         delete node;
00129       }
00130     }
00131 
00133     bool ensureCached( typename T::Id id, const FetchScope &scope )
00134     {
00135       EntityCacheNode<T>* node = cacheNodeForId( id );
00136       if ( !node ) {
00137         request( id, scope );
00138         return false;
00139       }
00140       return !node->pending;
00141     }
00142 
00148     void request( typename T::Id id, const FetchScope &scope )
00149     {
00150       Q_ASSERT( !isRequested( id ) );
00151       shrinkCache();
00152       EntityCacheNode<T> *node = new EntityCacheNode<T>( id );
00153       FetchJob* job = createFetchJob( id );
00154       job->setFetchScope( scope );
00155       job->setProperty( "EntityCacheNode", QVariant::fromValue<typename T::Id>( id ) );
00156       connect( job, SIGNAL(result(KJob*)), SLOT(fetchResult(KJob*)) );
00157       mCache.enqueue( node );
00158     }
00159 
00160   private:
00161     EntityCacheNode<T>* cacheNodeForId( typename T::Id id ) const
00162     {
00163       for ( typename QQueue<EntityCacheNode<T>*>::const_iterator it = mCache.constBegin(), endIt = mCache.constEnd();
00164             it != endIt; ++it )
00165       {
00166         if ( (*it)->entity.id() == id )
00167           return *it;
00168       }
00169       return 0;
00170     }
00171 
00172     void fetchResult( KJob* job )
00173     {
00174       typename T::Id id = job->property( "EntityCacheNode" ).template value<typename T::Id>();
00175       EntityCacheNode<T> *node = cacheNodeForId( id );
00176       if ( !node )
00177         return; // got replaced in the meantime
00178 
00179       node->pending = false;
00180       extractResult( node, job );
00181       // make sure we find this node again if something went wrong here,
00182       // most likely the object got deleted from the server in the meantime
00183       if ( node->entity.id() != id ) {
00184         node->entity.setId( id );
00185         node->invalid = true;
00186       }
00187       emit dataAvailable();
00188     }
00189 
00190     void extractResult( EntityCacheNode<T>* node, KJob* job ) const;
00191 
00192     inline FetchJob* createFetchJob( typename T::Id id )
00193     {
00194       return new FetchJob( T( id ), session );
00195     }
00196 
00198     void shrinkCache()
00199     {
00200       while ( mCache.size() >= mCapacity && !mCache.first()->pending )
00201         delete mCache.dequeue();
00202     }
00203 
00204   private:
00205     QQueue<EntityCacheNode<T>*> mCache;
00206     int mCapacity;
00207 };
00208 
00209 template<> inline void EntityCache<Collection, CollectionFetchJob, CollectionFetchScope>::extractResult( EntityCacheNode<Collection>* node, KJob *job ) const
00210 {
00211   CollectionFetchJob* fetch = qobject_cast<CollectionFetchJob*>( job );
00212   Q_ASSERT( fetch );
00213   if ( fetch->collections().isEmpty() )
00214     node->entity = Collection();
00215   else
00216     node->entity = fetch->collections().first();
00217 }
00218 
00219 template<> inline void EntityCache<Item, ItemFetchJob, ItemFetchScope>::extractResult( EntityCacheNode<Item>* node, KJob *job ) const
00220 {
00221   ItemFetchJob* fetch = qobject_cast<ItemFetchJob*>( job );
00222   Q_ASSERT( fetch );
00223   if ( fetch->items().isEmpty() )
00224     node->entity = Item();
00225   else
00226     node->entity = fetch->items().first();
00227 }
00228 
00229 template<> inline CollectionFetchJob* EntityCache<Collection, CollectionFetchJob, CollectionFetchScope>::createFetchJob( Collection::Id id )
00230 {
00231   return new CollectionFetchJob( Collection( id ), CollectionFetchJob::Base, session );
00232 }
00233 
00234 typedef EntityCache<Collection, CollectionFetchJob, CollectionFetchScope> CollectionCache;
00235 typedef EntityCache<Item, ItemFetchJob, ItemFetchScope> ItemCache;
00236 
00237 }
00238 
00239 #endif

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal