22 #include "itemserializer_p.h"
23 #include "protocol_p.h"
28 #include <QtCore/QStringList>
29 #include <QtCore/QReadWriteLock>
35 using namespace Akonadi;
36 using namespace boost;
42 void operator()( T * ) {}
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 ;
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 ) )
58 void Item::addToLegacyMappingImpl( const QString & mimeType,
int spid,
int mtid, std::auto_ptr<PayloadBase> p ) {
62 const boost::shared_ptr<PayloadBase> sp( p );
63 const QWriteLocker locker( legacyMapLock() );
64 std::pair<int,int> & item = ( *typeInfoToMetaTypeIdMap() )[mimeType][sp];
72 explicit MyReadLocker( QReadWriteLock * rwl ) : rwl( rwl ), locked( false ) {
if ( rwl ) rwl->lockForRead(); locked =
true; }
73 ~MyReadLocker() {
if ( rwl && locked ) rwl->unlock(); }
76 shared_ptr<T> makeUnlockingPointer( T * t ) {
82 const shared_ptr<T> result( t, bind( &QReadWriteLock::unlock, rwl ) );
86 return shared_ptr<T>();
90 QReadWriteLock *
const rwl;
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> >();
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> >();
107 return locker.makeUnlockingPointer( &it->second );
111 const char* Item::FullPayload =
"RFC822";
123 Item::Item(
const QString & mimeType )
126 d_func()->mMimeType = mimeType;
129 Item::Item(
const Item &other )
138 Item::Flags Item::flags()
const
140 return d_func()->mFlags;
143 void Item::setFlag(
const QByteArray & name )
146 d->mFlags.insert( name );
147 if ( !d->mFlagsOverwritten ) {
148 if ( d->mDeletedFlags.contains( name ) ) {
149 d->mDeletedFlags.remove( name );
151 d->mAddedFlags.insert( name );
156 void Item::clearFlag(
const QByteArray & name )
159 d->mFlags.remove( name );
160 if ( !d->mFlagsOverwritten ) {
161 if ( d->mAddedFlags.contains( name ) ) {
162 d->mAddedFlags.remove( name );
164 d->mDeletedFlags.insert( name );
169 void Item::setFlags(
const Flags &flags )
173 d->mFlagsOverwritten =
true;
176 void Item::clearFlags()
180 d->mFlagsOverwritten =
true;
183 QDateTime Item::modificationTime()
const
185 return d_func()->mModificationTime;
188 void Item::setModificationTime(
const QDateTime &datetime )
190 d_func()->mModificationTime = datetime;
193 bool Item::hasFlag(
const QByteArray & name )
const
195 return d_func()->mFlags.contains( name );
198 void Item::setTags(
const Tag::List& list )
202 d->mTagsOverwritten =
true;
205 void Item::setTag(
const Tag &tag )
209 if ( !d->mTagsOverwritten ) {
210 if ( d->mDeletedTags.contains( tag ) ) {
211 d->mDeletedTags.removeOne( tag );
213 d->mAddedTags << tag ;
218 void Item::clearTags()
222 d->mTagsOverwritten =
true;
225 void Item::clearTag(
const Tag &tag )
228 d->mTags.removeOne( tag );
229 if ( !d->mTagsOverwritten ) {
230 if ( d->mAddedTags.contains( tag ) ) {
231 d->mAddedTags.removeOne( tag );
233 d->mDeletedTags << tag;
238 bool Item::hasTag(
const Tag &tag )
const
241 return d->mTags.contains( tag );
244 Tag::List Item::tags()
const
250 QSet<QByteArray> Item::loadedPayloadParts()
const
255 QByteArray Item::payloadData()
const
263 void Item::setPayloadFromData(
const QByteArray &data )
268 void Item::clearPayload()
270 d_func()->mClearPayload =
true;
273 int Item::revision()
const
275 return d_func()->mRevision;
278 void Item::setRevision(
int rev )
280 d_func()->mRevision = rev;
285 return d_func()->mCollectionId;
288 void Item::setStorageCollectionId(
Entity::Id collectionId )
290 d_func()->mCollectionId = collectionId;
293 QString Item::mimeType()
const
295 return d_func()->mMimeType;
298 void Item::setSize( qint64 size )
302 d->mSizeChanged =
true;
305 qint64 Item::size()
const
307 return d_func()->mSize;
310 void Item::setMimeType(
const QString & mimeType )
312 d_func()->mMimeType = mimeType;
315 void Item::setGid(
const QString &
id )
320 QString Item::gid()
const
322 return d_func()->mGid;
325 bool Item::hasPayload()
const
327 return d_func()->hasMetaTypeId( -1 );
330 KUrl Item::url( UrlType type )
const
333 url.setProtocol( QString::fromLatin1(
"akonadi" ) );
334 url.addQueryItem( QLatin1String(
"item" ), QString::number(
id() ) );
336 if ( type == UrlWithMimeType ) {
337 url.addQueryItem( QLatin1String(
"type" ), mimeType() );
343 Item Item::fromUrl(
const KUrl &url )
345 if ( url.protocol() != QLatin1String(
"akonadi" ) ) {
349 const QString itemStr = url.queryItem( QLatin1String(
"item" ) );
351 Item::Id itemId = itemStr.toLongLong( &ok );
356 return Item( itemId );
363 Q_GLOBAL_STATIC( Payload<Dummy>, dummyPayload )
365 PayloadBase* Item::payloadBase()
const
368 d->tryEnsureLegacyPayload();
369 if ( d->mLegacyPayload ) {
370 return d->mLegacyPayload.get();
372 return dummyPayload();
376 void ItemPrivate::tryEnsureLegacyPayload()
const
378 if ( !mLegacyPayload ) {
379 for ( PayloadContainer::const_iterator it = mPayloads.begin(), end = mPayloads.end() ; it != end ; ++it ) {
380 if ( lookupLegacyMapping( mMimeType, it->payload.get() ) ) {
381 mLegacyPayload = it->payload;
387 PayloadBase* Item::payloadBaseV2(
int spid,
int mtid )
const
389 return d_func()->payloadBaseImpl( spid, mtid );
393 class ConversionGuard {
397 explicit ConversionGuard(
bool & b )
408 bool Item::ensureMetaTypeId(
int mtid )
const
412 if ( d->mPayloads.empty() ) {
417 if ( d->hasMetaTypeId( mtid ) ) {
423 if ( d->mConversionInProgress ) {
429 const ConversionGuard guard( d->mConversionInProgress );
431 return d->movePayloadFrom( converted.d_func(), mtid );
432 }
catch (
const std::exception & e ) {
433 kDebug() <<
"conversion threw:" << e.what();
436 kDebug() <<
"conversion threw something not derived from std::exception: fix the program!";
441 static QString format_type(
int spid,
int mtid ) {
442 return QString::fromLatin1(
"sp(%1)<%2>" )
443 .arg( spid ).arg( QLatin1String( QMetaType::typeName( mtid ) ) );
446 static QString format_types(
const PayloadContainer & c ) {
448 for ( PayloadContainer::const_iterator it = c.begin(), end = c.end() ; it != end ; ++it ) {
449 result.push_back( format_type( it->sharedPointerId, it->metaTypeId ) );
451 return result.join( QLatin1String(
", " ) );
455 QString Item::payloadExceptionText(
int spid,
int mtid )
const
458 if ( d->mPayloads.empty() ) {
459 return QLatin1String(
"No payload set" );
461 return QString::fromLatin1(
"Wrong payload type (requested: %1; present: %2" )
462 .arg( format_type( spid, mtid ), format_types( d->mPayloads ) );
466 void Item::throwPayloadException(
int spid,
int mtid )
const
469 if ( d->mPayloads.empty() ) {
470 throw PayloadException(
"No payload set" );
472 throw PayloadException( QString::fromLatin1(
"Wrong payload type (requested: %1; present: %2" )
473 .arg( format_type( spid, mtid ), format_types( d->mPayloads ) ) );
478 void Item::setPayloadBase( PayloadBase* p )
480 d_func()->setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase>( p ) );
483 void ItemPrivate::setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase> p )
485 if (
const shared_ptr<
const std::pair<int,int> > pair = lookupLegacyMapping( mMimeType, p.get() ) ) {
486 std::auto_ptr<PayloadBase> clone;
488 clone.reset( p->clone() );
490 setPayloadBaseImpl( pair->first, pair->second, p,
false );
491 mLegacyPayload.reset( clone.release() );
494 mLegacyPayload.reset( p.release() );
498 void Item::setPayloadBaseV2(
int spid,
int mtid, std::auto_ptr<PayloadBase> p )
500 d_func()->setPayloadBaseImpl( spid, mtid, p,
false );
503 void Item::addPayloadBaseVariant(
int spid,
int mtid, std::auto_ptr<PayloadBase> p )
const
505 d_func()->setPayloadBaseImpl( spid, mtid, p,
true );
508 QSet<QByteArray> Item::cachedPayloadParts()
const
511 return d->mCachedPayloadParts;
514 void Item::setCachedPayloadParts(
const QSet< QByteArray > &cachedParts)
517 d->mCachedPayloadParts = cachedParts;
520 QSet<QByteArray> Item::availablePayloadParts()
const
525 QVector<int> Item::availablePayloadMetaTypeIds()
const
529 result.reserve( d->mPayloads.size() );
531 for ( PayloadContainer::const_iterator it = d->mPayloads.begin(), end = d->mPayloads.end() ; it != end ; ++it ) {
532 result.insert( std::upper_bound( result.begin(), result.end(), it->metaTypeId ), it->metaTypeId );
537 void Item::apply(
const Item &other )
539 if ( mimeType() != other.mimeType() || id() != other.id() ) {
540 kDebug() <<
"mimeType() = " << mimeType() <<
"; other.mimeType() = " << other.mimeType();
541 kDebug() <<
"id() = " << id() <<
"; other.id() = " << other.id();
542 Q_ASSERT_X(
false,
"Item::apply",
"mimetype or id missmatch" );
545 setRemoteId( other.remoteId() );
546 setRevision( other.revision() );
547 setRemoteRevision( other.remoteRevision() );
548 setFlags( other.flags() );
549 setTags( other.tags() );
550 setModificationTime( other.modificationTime() );
551 setSize( other.size() );
552 setParentCollection( other.parentCollection() );
553 setStorageCollectionId( other.storageCollectionId() );
555 QList<QByteArray> attrs;
556 foreach (
Attribute *attribute, other.attributes() ) {
557 addAttribute( attribute->
clone() );
558 attrs.append( attribute->
type() );
561 QMutableHashIterator<QByteArray, Attribute*> it( d_ptr->mAttributes );
562 while ( it.hasNext() ) {
564 if ( !attrs.contains( it.key() ) ) {
571 d_func()->resetChangeLog();
574 AKONADI_DEFINE_PRIVATE( Item )
qint64 Id
Describes the unique id type.
Provides interface for custom attributes for Entity.
static Item convert(const Item &item, int metaTypeId)
Tries to convert the payload in item into type with metatype-id metaTypeId.
static QSet< QByteArray > parts(const Item &item)
Returns a list of parts available in the item payload.
static void apply(Item &item, const Item &other)
Throws ItemSerializerException on failure.
static void deserialize(Item &item, const QByteArray &label, const QByteArray &data, int version, bool external)
throws ItemSerializerException on failure
The base class for Item and Collection.
static void serialize(const Item &item, const QByteArray &label, QByteArray &data, int &version)
throws ItemSerializerException on failure
virtual Attribute * clone() const =0
Creates a copy of this attribute.
virtual QByteArray type() const =0
Returns the type of the attribute.
static QSet< QByteArray > availableParts(const Item &item)
Returns a list of parts available remotely in the item payload.