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 ) {
61 const boost::shared_ptr<PayloadBase> sp( p );
62 const QWriteLocker locker( legacyMapLock() );
63 std::pair<int,int> & item = (*typeInfoToMetaTypeIdMap())[mimeType][sp];
71 explicit MyReadLocker( QReadWriteLock * rwl ) : rwl( rwl ), locked( false ) {
if ( rwl ) rwl->lockForRead(); locked =
true; }
72 ~MyReadLocker() {
if ( rwl && locked ) rwl->unlock(); }
75 shared_ptr<T> makeUnlockingPointer( T * t ) {
81 const shared_ptr<T> result( t, bind( &QReadWriteLock::unlock, rwl ) );
85 return shared_ptr<T>();
89 QReadWriteLock *
const rwl;
94 static shared_ptr<const std::pair<int,int> > lookupLegacyMapping(
const QString & mimeType, PayloadBase * p ) {
95 MyReadLocker locker( legacyMapLock() );
96 const LegacyMap::const_iterator hit = typeInfoToMetaTypeIdMap()->constFind( mimeType );
97 if ( hit == typeInfoToMetaTypeIdMap()->constEnd() )
98 return shared_ptr<const std::pair<int,int> >();
99 const boost::shared_ptr<PayloadBase> sp( p, nodelete() );
100 const LegacyMap::mapped_type::const_iterator it = hit->find( sp );
101 if ( it == hit->end() )
102 return shared_ptr<
const std::pair<int,int> >();
104 return locker.makeUnlockingPointer( &it->second );
137 return d_func()->mFlags;
143 d->mFlags.insert( name );
144 if ( !d->mFlagsOverwritten ) {
145 if ( d->mDeletedFlags.contains( name ) )
146 d->mDeletedFlags.remove( name );
148 d->mAddedFlags.insert( name );
155 d->mFlags.remove( name );
156 if ( !d->mFlagsOverwritten ) {
157 if ( d->mAddedFlags.contains( name ) )
158 d->mAddedFlags.remove( name );
160 d->mDeletedFlags.insert( name );
168 d->mFlagsOverwritten =
true;
175 d->mFlagsOverwritten =
true;
180 return d_func()->mModificationTime;
185 d_func()->mModificationTime = datetime;
190 return d_func()->mFlags.contains( name );
213 d_func()->mClearPayload =
true;
218 return d_func()->mRevision;
223 d_func()->mRevision = rev;
228 return d_func()->mCollectionId;
231 void Item::setStorageCollectionId(
Entity::Id collectionId )
233 d_func()->mCollectionId = collectionId;
238 return d_func()->mMimeType;
245 d->mSizeChanged =
true;
250 return d_func()->mSize;
260 return d_func()->hasMetaTypeId( -1 );
266 url.setProtocol( QString::fromLatin1(
"akonadi" ) );
267 url.addQueryItem( QLatin1String(
"item" ), QString::number(
id() ) );
270 url.addQueryItem( QLatin1String(
"type" ),
mimeType() );
277 if ( url.protocol() != QLatin1String(
"akonadi" ) )
280 const QString itemStr = url.queryItem( QLatin1String(
"item" ) );
282 Item::Id itemId = itemStr.toLongLong( &ok );
286 return Item( itemId );
293 Q_GLOBAL_STATIC( Payload<Dummy>, dummyPayload )
295 PayloadBase*
Item::payloadBase()
const
298 d->tryEnsureLegacyPayload();
299 if ( d->mLegacyPayload )
300 return d->mLegacyPayload.get();
302 return dummyPayload();
305 void ItemPrivate::tryEnsureLegacyPayload()
const
307 if ( !mLegacyPayload )
308 for ( PayloadContainer::const_iterator it = mPayloads.begin(), end = mPayloads.end() ; it != end ; ++it )
309 if ( lookupLegacyMapping( mMimeType, it->payload.get() ) )
310 mLegacyPayload = it->payload;
313 PayloadBase* Item::payloadBaseV2(
int spid,
int mtid )
const
315 return d_func()->payloadBaseImpl( spid, mtid );
319 class ConversionGuard {
323 explicit ConversionGuard(
bool & b )
335 bool Item::ensureMetaTypeId(
int mtid )
const
339 if ( d->mPayloads.empty() )
343 if ( d->hasMetaTypeId( mtid ) )
348 if ( d->mConversionInProgress )
353 const ConversionGuard guard( d->mConversionInProgress );
355 return d->movePayloadFrom( converted.d_func(), mtid );
356 }
catch (
const std::exception & e ) {
357 kDebug() <<
"conversion threw:" << e.what();
360 kDebug() <<
"conversion threw something not derived from std::exception: fix the program!";
365 static QString format_type(
int spid,
int mtid ) {
366 return QString::fromLatin1(
"sp(%1)<%2>" )
367 .arg( spid ).arg( QLatin1String( QMetaType::typeName( mtid ) ) );
370 static QString format_types(
const PayloadContainer & c ) {
372 for ( PayloadContainer::const_iterator it = c.begin(), end = c.end() ; it != end ; ++it )
373 result.push_back( format_type( it->sharedPointerId, it->metaTypeId ) );
374 return result.join( QLatin1String(
", ") );
378 QString Item::payloadExceptionText(
int spid,
int mtid )
const
381 if ( d->mPayloads.empty() )
382 return QLatin1String(
"No payload set" );
384 return QString::fromLatin1(
"Wrong payload type (requested: %1; present: %2" )
385 .arg( format_type( spid, mtid ), format_types( d->mPayloads ) );
388 void Item::throwPayloadException(
int spid,
int mtid )
const
391 if ( d->mPayloads.empty() )
392 throw PayloadException(
"No payload set" );
394 throw PayloadException( QString::fromLatin1(
"Wrong payload type (requested: %1; present: %2" )
395 .arg( format_type( spid, mtid ), format_types( d->mPayloads ) ) );
399 void Item::setPayloadBase( PayloadBase* p )
401 d_func()->setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase>( p ) );
404 void ItemPrivate::setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase> p )
406 if (
const shared_ptr<
const std::pair<int,int> > pair = lookupLegacyMapping( mMimeType, p.get() ) ) {
407 std::auto_ptr<PayloadBase> clone;
409 clone.reset( p->clone() );
410 setPayloadBaseImpl( pair->first, pair->second, p,
false );
411 mLegacyPayload.reset( clone.release() );
414 mLegacyPayload.reset( p.release() );
418 void Item::setPayloadBaseV2(
int spid,
int mtid, std::auto_ptr<PayloadBase> p )
420 d_func()->setPayloadBaseImpl( spid, mtid, p,
false );
423 void Item::addPayloadBaseVariant(
int spid,
int mtid, std::auto_ptr<PayloadBase> p )
const
425 d_func()->setPayloadBaseImpl( spid, mtid, p,
true );
437 result.reserve( d->mPayloads.size() );
439 for ( PayloadContainer::const_iterator it = d->mPayloads.begin(), end = d->mPayloads.end() ; it != end ; ++it )
440 result.insert( std::upper_bound( result.begin(), result.end(), it->metaTypeId ), it->metaTypeId );
447 kDebug() <<
"mimeType() = " <<
mimeType() <<
"; other.mimeType() = " << other.
mimeType();
448 kDebug() <<
"id() = " <<
id() <<
"; other.id() = " << other.
id();
449 Q_ASSERT_X(
false,
"Item::apply",
"mimetype or id missmatch" );
461 QList<QByteArray> attrs;
465 attrs.append( attribute->
type() );
468 QMutableHashIterator<QByteArray, Attribute*> it( d_ptr->mAttributes );
469 while ( it.hasNext() ) {
471 if ( !attrs.contains( it.key() ) ) {
478 d_func()->resetChangeLog();
481 AKONADI_DEFINE_PRIVATE(
Item )