• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.11.3 API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • akonadi
item.cpp
1 /*
2  Copyright (c) 2006 Volker Krause <vkrause@kde.org>
3 
4  This library is free software; you can redistribute it and/or modify it
5  under the terms of the GNU Library General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or (at your
7  option) any later version.
8 
9  This library is distributed in the hope that it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12  License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to the
16  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  02110-1301, USA.
18 */
19 
20 #include "item.h"
21 #include "item_p.h"
22 #include "itemserializer_p.h"
23 #include "protocol_p.h"
24 
25 #include <kurl.h>
26 #include <kdebug.h>
27 
28 #include <QtCore/QStringList>
29 #include <QtCore/QReadWriteLock>
30 
31 #include <algorithm>
32 #include <map>
33 #include <utility>
34 
35 using namespace Akonadi;
36 using namespace boost;
37 
38 namespace {
39 
40 struct nodelete {
41  template <typename T>
42  void operator()( T * ) {}
43 };
44 
45 struct ByTypeId {
46  typedef bool result_type;
47  bool operator()( const boost::shared_ptr<PayloadBase> & lhs, const boost::shared_ptr<PayloadBase> & rhs ) const {
48  return strcmp( lhs->typeName(), rhs->typeName() ) < 0 ;
49  }
50 };
51 
52 } // anon namespace
53 
54 typedef QHash< QString, std::map< boost::shared_ptr<PayloadBase>, std::pair<int,int>, ByTypeId > > LegacyMap;
55 Q_GLOBAL_STATIC( LegacyMap, typeInfoToMetaTypeIdMap )
56 Q_GLOBAL_STATIC_WITH_ARGS( QReadWriteLock, legacyMapLock, ( QReadWriteLock::Recursive ) )
57 
58 void Item::addToLegacyMappingImpl( const QString & mimeType, int spid, int mtid, std::auto_ptr<PayloadBase> p ) {
59  if ( !p.get() ) {
60  return;
61  }
62  const boost::shared_ptr<PayloadBase> sp( p );
63  const QWriteLocker locker( legacyMapLock() );
64  std::pair<int,int> & item = ( *typeInfoToMetaTypeIdMap() )[mimeType][sp];
65  item.first = spid;
66  item.second = mtid;
67 }
68 
69 namespace {
70  class MyReadLocker {
71  public:
72  explicit MyReadLocker( QReadWriteLock * rwl ) : rwl( rwl ), locked( false ) { if ( rwl ) rwl->lockForRead(); locked = true; }
73  ~MyReadLocker() { if ( rwl && locked ) rwl->unlock(); }
74 
75  template <typename T>
76  shared_ptr<T> makeUnlockingPointer( T * t ) {
77  if ( t ) {
78  // the bind() doesn't throw, so if shared_ptr
79  // construction line below, or anything else after it,
80  // throws, we're unlocked. Mark us as such:
81  locked = false;
82  const shared_ptr<T> result( t, bind( &QReadWriteLock::unlock, rwl ) );
83  // from now on, the shared_ptr is responsible for unlocking
84  return result;
85  } else {
86  return shared_ptr<T>();
87  }
88  }
89  private:
90  QReadWriteLock * const rwl;
91  bool locked;
92  };
93 }
94 
95 static shared_ptr<const std::pair<int,int> > lookupLegacyMapping( const QString & mimeType, PayloadBase * p ) {
96  MyReadLocker locker( legacyMapLock() );
97  const LegacyMap::const_iterator hit = typeInfoToMetaTypeIdMap()->constFind( mimeType );
98  if ( hit == typeInfoToMetaTypeIdMap()->constEnd() ) {
99  return shared_ptr<const std::pair<int,int> >();
100  }
101  const boost::shared_ptr<PayloadBase> sp( p, nodelete() );
102  const LegacyMap::mapped_type::const_iterator it = hit->find( sp );
103  if ( it == hit->end() ) {
104  return shared_ptr<const std::pair<int,int> >();
105  }
106 
107  return locker.makeUnlockingPointer( &it->second );
108 }
109 
110 // Change to something != RFC822 as soon as the server supports it
111 const char* Item::FullPayload = "RFC822";
112 
113 Item::Item()
114  : Entity( new ItemPrivate )
115 {
116 }
117 
118 Item::Item( Id id )
119  : Entity( new ItemPrivate( id ) )
120 {
121 }
122 
123 Item::Item( const QString & mimeType )
124  : Entity( new ItemPrivate )
125 {
126  d_func()->mMimeType = mimeType;
127 }
128 
129 Item::Item( const Item &other )
130  : Entity( other )
131 {
132 }
133 
134 Item::~Item()
135 {
136 }
137 
138 Item::Flags Item::flags() const
139 {
140  return d_func()->mFlags;
141 }
142 
143 void Item::setFlag( const QByteArray & name )
144 {
145  Q_D( Item );
146  d->mFlags.insert( name );
147  if ( !d->mFlagsOverwritten ) {
148  if ( d->mDeletedFlags.contains( name ) ) {
149  d->mDeletedFlags.remove( name );
150  } else {
151  d->mAddedFlags.insert( name );
152  }
153  }
154 }
155 
156 void Item::clearFlag( const QByteArray & name )
157 {
158  Q_D( Item );
159  d->mFlags.remove( name );
160  if ( !d->mFlagsOverwritten ) {
161  if ( d->mAddedFlags.contains( name ) ) {
162  d->mAddedFlags.remove( name );
163  } else {
164  d->mDeletedFlags.insert( name );
165  }
166  }
167 }
168 
169 void Item::setFlags( const Flags &flags )
170 {
171  Q_D( Item );
172  d->mFlags = flags;
173  d->mFlagsOverwritten = true;
174 }
175 
176 void Item::clearFlags()
177 {
178  Q_D( Item );
179  d->mFlags.clear();
180  d->mFlagsOverwritten = true;
181 }
182 
183 QDateTime Item::modificationTime() const
184 {
185  return d_func()->mModificationTime;
186 }
187 
188 void Item::setModificationTime( const QDateTime &datetime )
189 {
190  d_func()->mModificationTime = datetime;
191 }
192 
193 bool Item::hasFlag( const QByteArray & name ) const
194 {
195  return d_func()->mFlags.contains( name );
196 }
197 
198 QSet<QByteArray> Item::loadedPayloadParts() const
199 {
200  return ItemSerializer::parts( *this );
201 }
202 
203 QByteArray Item::payloadData() const
204 {
205  int version = 0;
206  QByteArray data;
207  ItemSerializer::serialize( *this, FullPayload, data, version );
208  return data;
209 }
210 
211 void Item::setPayloadFromData( const QByteArray &data )
212 {
213  ItemSerializer::deserialize( *this, FullPayload, data, 0, false );
214 }
215 
216 void Item::clearPayload()
217 {
218  d_func()->mClearPayload = true;
219 }
220 
221 int Item::revision() const
222 {
223  return d_func()->mRevision;
224 }
225 
226 void Item::setRevision( int rev )
227 {
228  d_func()->mRevision = rev;
229 }
230 
231 Entity::Id Item::storageCollectionId() const
232 {
233  return d_func()->mCollectionId;
234 }
235 
236 void Item::setStorageCollectionId( Entity::Id collectionId )
237 {
238  d_func()->mCollectionId = collectionId;
239 }
240 
241 QString Item::mimeType() const
242 {
243  return d_func()->mMimeType;
244 }
245 
246 void Item::setSize( qint64 size )
247 {
248  Q_D( Item );
249  d->mSize = size;
250  d->mSizeChanged = true;
251 }
252 
253 qint64 Item::size() const
254 {
255  return d_func()->mSize;
256 }
257 
258 void Item::setMimeType( const QString & mimeType )
259 {
260  d_func()->mMimeType = mimeType;
261 }
262 
263 bool Item::hasPayload() const
264 {
265  return d_func()->hasMetaTypeId( -1 );
266 }
267 
268 KUrl Item::url( UrlType type ) const
269 {
270  KUrl url;
271  url.setProtocol( QString::fromLatin1( "akonadi" ) );
272  url.addQueryItem( QLatin1String( "item" ), QString::number( id() ) );
273 
274  if ( type == UrlWithMimeType ) {
275  url.addQueryItem( QLatin1String( "type" ), mimeType() );
276  }
277 
278  return url;
279 }
280 
281 Item Item::fromUrl( const KUrl &url )
282 {
283  if ( url.protocol() != QLatin1String( "akonadi" ) ) {
284  return Item();
285  }
286 
287  const QString itemStr = url.queryItem( QLatin1String( "item" ) );
288  bool ok = false;
289  Item::Id itemId = itemStr.toLongLong( &ok );
290  if ( !ok ) {
291  return Item();
292  }
293 
294  return Item( itemId );
295 }
296 
297 namespace {
298  class Dummy {};
299 }
300 
301 Q_GLOBAL_STATIC( Payload<Dummy>, dummyPayload )
302 
303 PayloadBase* Item::payloadBase() const
304 {
305  Q_D( const Item );
306  d->tryEnsureLegacyPayload();
307  if ( d->mLegacyPayload ) {
308  return d->mLegacyPayload.get();
309  } else {
310  return dummyPayload();
311  }
312 }
313 
314 void ItemPrivate::tryEnsureLegacyPayload() const
315 {
316  if ( !mLegacyPayload ) {
317  for ( PayloadContainer::const_iterator it = mPayloads.begin(), end = mPayloads.end() ; it != end ; ++it ) {
318  if ( lookupLegacyMapping( mMimeType, it->payload.get() ) ) {
319  mLegacyPayload = it->payload; // clones
320  }
321  }
322  }
323 }
324 
325 PayloadBase* Item::payloadBaseV2( int spid, int mtid ) const
326 {
327  return d_func()->payloadBaseImpl( spid, mtid );
328 }
329 
330 namespace {
331  class ConversionGuard {
332  const bool old;
333  bool & b;
334  public:
335  explicit ConversionGuard( bool & b )
336  : old( b ), b( b )
337  {
338  b = true;
339  }
340  ~ConversionGuard() {
341  b = old;
342  }
343  };
344 }
345 
346 bool Item::ensureMetaTypeId( int mtid ) const
347 {
348  Q_D( const Item );
349  // 0. Nothing there - nothing to convert from, either
350  if ( d->mPayloads.empty() ) {
351  return false;
352  }
353 
354  // 1. Look whether we already have one:
355  if ( d->hasMetaTypeId( mtid ) ) {
356  return true;
357  }
358 
359  // recursion detection (shouldn't trigger, but does if the
360  // serialiser plugins are acting funky):
361  if ( d->mConversionInProgress ) {
362  return false;
363  }
364 
365  // 2. Try to create one by conversion from a different representation:
366  try {
367  const ConversionGuard guard( d->mConversionInProgress );
368  Item converted = ItemSerializer::convert( *this, mtid );
369  return d->movePayloadFrom( converted.d_func(), mtid );
370  } catch ( const std::exception & e ) {
371  kDebug() << "conversion threw:" << e.what();
372  return false;
373  } catch ( ... ) {
374  kDebug() << "conversion threw something not derived from std::exception: fix the program!";
375  return false;
376  }
377 }
378 
379 static QString format_type( int spid, int mtid ) {
380  return QString::fromLatin1( "sp(%1)<%2>" )
381  .arg( spid ).arg( QLatin1String( QMetaType::typeName( mtid ) ) );
382 }
383 
384 static QString format_types( const PayloadContainer & c ) {
385  QStringList result;
386  for ( PayloadContainer::const_iterator it = c.begin(), end = c.end() ; it != end ; ++it ) {
387  result.push_back( format_type( it->sharedPointerId, it->metaTypeId ) );
388  }
389  return result.join( QLatin1String( ", " ) );
390 }
391 
392 #if 0
393 QString Item::payloadExceptionText( int spid, int mtid ) const
394 {
395  Q_D( const Item );
396  if ( d->mPayloads.empty() ) {
397  return QLatin1String( "No payload set" );
398  } else {
399  return QString::fromLatin1( "Wrong payload type (requested: %1; present: %2" )
400  .arg( format_type( spid, mtid ), format_types( d->mPayloads ) );
401  }
402 }
403 #else
404 void Item::throwPayloadException( int spid, int mtid ) const
405 {
406  Q_D( const Item );
407  if ( d->mPayloads.empty() ) {
408  throw PayloadException( "No payload set" );
409  } else {
410  throw PayloadException( QString::fromLatin1( "Wrong payload type (requested: %1; present: %2" )
411  .arg( format_type( spid, mtid ), format_types( d->mPayloads ) ) );
412  }
413 }
414 #endif
415 
416 void Item::setPayloadBase( PayloadBase* p )
417 {
418  d_func()->setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase>( p ) );
419 }
420 
421 void ItemPrivate::setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase> p )
422 {
423  if ( const shared_ptr<const std::pair<int,int> > pair = lookupLegacyMapping( mMimeType, p.get() ) ) {
424  std::auto_ptr<PayloadBase> clone;
425  if ( p.get() ) {
426  clone.reset( p->clone() );
427  }
428  setPayloadBaseImpl( pair->first, pair->second, p, false );
429  mLegacyPayload.reset( clone.release() );
430  } else {
431  mPayloads.clear();
432  mLegacyPayload.reset( p.release() );
433  }
434 }
435 
436 void Item::setPayloadBaseV2( int spid, int mtid, std::auto_ptr<PayloadBase> p )
437 {
438  d_func()->setPayloadBaseImpl( spid, mtid, p, false );
439 }
440 
441 void Item::addPayloadBaseVariant( int spid, int mtid, std::auto_ptr<PayloadBase> p ) const
442 {
443  d_func()->setPayloadBaseImpl( spid, mtid, p, true );
444 }
445 
446 QSet<QByteArray> Item::cachedPayloadParts() const
447 {
448  Q_D(const Item);
449  return d->mCachedPayloadParts;
450 }
451 
452 void Item::setCachedPayloadParts(const QSet< QByteArray > &cachedParts)
453 {
454  Q_D(Item);
455  d->mCachedPayloadParts = cachedParts;
456 }
457 
458 QSet<QByteArray> Item::availablePayloadParts() const
459 {
460  return ItemSerializer::availableParts( *this );
461 }
462 
463 QVector<int> Item::availablePayloadMetaTypeIds() const
464 {
465  QVector<int> result;
466  Q_D( const Item );
467  result.reserve( d->mPayloads.size() );
468  // Stable Insertion Sort - N is typically _very_ low (1 or 2).
469  for ( PayloadContainer::const_iterator it = d->mPayloads.begin(), end = d->mPayloads.end() ; it != end ; ++it ) {
470  result.insert( std::upper_bound( result.begin(), result.end(), it->metaTypeId ), it->metaTypeId );
471  }
472  return result;
473 }
474 
475 void Item::apply( const Item &other )
476 {
477  if ( mimeType() != other.mimeType() || id() != other.id() ) {
478  kDebug() << "mimeType() = " << mimeType() << "; other.mimeType() = " << other.mimeType();
479  kDebug() << "id() = " << id() << "; other.id() = " << other.id();
480  Q_ASSERT_X( false, "Item::apply", "mimetype or id missmatch" );
481  }
482 
483  setRemoteId( other.remoteId() );
484  setRevision( other.revision() );
485  setRemoteRevision( other.remoteRevision() );
486  setFlags( other.flags() );
487  setModificationTime( other.modificationTime() );
488  setSize( other.size() );
489  setParentCollection( other.parentCollection() );
490  setStorageCollectionId( other.storageCollectionId() );
491 
492  QList<QByteArray> attrs;
493  foreach ( Attribute *attribute, other.attributes() ) {
494  addAttribute( attribute->clone() );
495  attrs.append( attribute->type() );
496  }
497 
498  QMutableHashIterator<QByteArray, Attribute*> it( d_ptr->mAttributes );
499  while ( it.hasNext() ) {
500  it.next();
501  if ( !attrs.contains( it.key() ) ) {
502  delete it.value();
503  it.remove();
504  }
505  }
506 
507  ItemSerializer::apply( *this, other );
508  d_func()->resetChangeLog();
509 }
510 
511 AKONADI_DEFINE_PRIVATE( Item )
Akonadi::Entity::Id
qint64 Id
Describes the unique id type.
Definition: entity.h:64
Akonadi::Attribute
Provides interface for custom attributes for Entity.
Definition: attribute.h:138
Akonadi::ItemSerializer::convert
static Item convert(const Item &item, int metaTypeId)
Tries to convert the payload in item into type with metatype-id metaTypeId.
Definition: itemserializer.cpp:179
Akonadi::ItemSerializer::parts
static QSet< QByteArray > parts(const Item &item)
Returns a list of parts available in the item payload.
Definition: itemserializer.cpp:156
Akonadi::ItemSerializer::apply
static void apply(Item &item, const Item &other)
Throws ItemSerializerException on failure.
Definition: itemserializer.cpp:129
Akonadi::ItemSerializer::deserialize
static void deserialize(Item &item, const QByteArray &label, const QByteArray &data, int version, bool external)
throws ItemSerializerException on failure
Definition: itemserializer.cpp:81
Akonadi::Entity
The base class for Item and Collection.
Definition: entity.h:58
Akonadi::ItemPrivate
Definition: item_p.h:163
Akonadi::ItemSerializer::serialize
static void serialize(const Item &item, const QByteArray &label, QByteArray &data, int &version)
throws ItemSerializerException on failure
Definition: itemserializer.cpp:110
Akonadi::Attribute::clone
virtual Attribute * clone() const =0
Creates a copy of this attribute.
Akonadi::Attribute::type
virtual QByteArray type() const =0
Returns the type of the attribute.
Akonadi::ItemSerializer::availableParts
static QSet< QByteArray > availableParts(const Item &item)
Returns a list of parts available remotely in the item payload.
Definition: itemserializer.cpp:163
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Tue Nov 26 2013 09:03:17 by doxygen 1.8.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

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

kdepimlibs-4.11.3 API Reference

Skip menu "kdepimlibs-4.11.3 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal