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 );
140 return d_func()->mFlags;
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 );
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 );
173 d->mFlagsOverwritten =
true;
180 d->mFlagsOverwritten =
true;
185 return d_func()->mModificationTime;
190 d_func()->mModificationTime = datetime;
195 return d_func()->mFlags.contains( name );
218 d_func()->mClearPayload =
true;
223 return d_func()->mRevision;
228 d_func()->mRevision = rev;
233 return d_func()->mCollectionId;
236 void Item::setStorageCollectionId(
Entity::Id collectionId )
238 d_func()->mCollectionId = collectionId;
243 return d_func()->mMimeType;
250 d->mSizeChanged =
true;
255 return d_func()->mSize;
265 return d_func()->hasMetaTypeId( -1 );
271 url.setProtocol( QString::fromLatin1(
"akonadi" ) );
272 url.addQueryItem( QLatin1String(
"item" ), QString::number(
id() ) );
275 url.addQueryItem( QLatin1String(
"type" ),
mimeType() );
283 if ( url.protocol() != QLatin1String(
"akonadi" ) ) {
287 const QString itemStr = url.queryItem( QLatin1String(
"item" ) );
289 Item::Id itemId = itemStr.toLongLong( &ok );
294 return Item( itemId );
301 Q_GLOBAL_STATIC( Payload<Dummy>, dummyPayload )
303 PayloadBase*
Item::payloadBase()
const
306 d->tryEnsureLegacyPayload();
307 if ( d->mLegacyPayload ) {
308 return d->mLegacyPayload.get();
310 return dummyPayload();
314 void ItemPrivate::tryEnsureLegacyPayload()
const
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;
325 PayloadBase* Item::payloadBaseV2(
int spid,
int mtid )
const
327 return d_func()->payloadBaseImpl( spid, mtid );
331 class ConversionGuard {
335 explicit ConversionGuard(
bool & b )
346 bool Item::ensureMetaTypeId(
int mtid )
const
350 if ( d->mPayloads.empty() ) {
355 if ( d->hasMetaTypeId( mtid ) ) {
361 if ( d->mConversionInProgress ) {
367 const ConversionGuard guard( d->mConversionInProgress );
369 return d->movePayloadFrom( converted.d_func(), mtid );
370 }
catch (
const std::exception & e ) {
371 kDebug() <<
"conversion threw:" << e.what();
374 kDebug() <<
"conversion threw something not derived from std::exception: fix the program!";
379 static QString format_type(
int spid,
int mtid ) {
380 return QString::fromLatin1(
"sp(%1)<%2>" )
381 .arg( spid ).arg( QLatin1String( QMetaType::typeName( mtid ) ) );
384 static QString format_types(
const PayloadContainer & c ) {
386 for ( PayloadContainer::const_iterator it = c.begin(), end = c.end() ; it != end ; ++it ) {
387 result.push_back( format_type( it->sharedPointerId, it->metaTypeId ) );
389 return result.join( QLatin1String(
", " ) );
393 QString Item::payloadExceptionText(
int spid,
int mtid )
const
396 if ( d->mPayloads.empty() ) {
397 return QLatin1String(
"No payload set" );
399 return QString::fromLatin1(
"Wrong payload type (requested: %1; present: %2" )
400 .arg( format_type( spid, mtid ), format_types( d->mPayloads ) );
404 void Item::throwPayloadException(
int spid,
int mtid )
const
407 if ( d->mPayloads.empty() ) {
408 throw PayloadException(
"No payload set" );
410 throw PayloadException( QString::fromLatin1(
"Wrong payload type (requested: %1; present: %2" )
411 .arg( format_type( spid, mtid ), format_types( d->mPayloads ) ) );
416 void Item::setPayloadBase( PayloadBase* p )
418 d_func()->setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase>( p ) );
421 void ItemPrivate::setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase> p )
423 if (
const shared_ptr<
const std::pair<int,int> > pair = lookupLegacyMapping( mMimeType, p.get() ) ) {
424 std::auto_ptr<PayloadBase> clone;
426 clone.reset( p->clone() );
428 setPayloadBaseImpl( pair->first, pair->second, p,
false );
429 mLegacyPayload.reset( clone.release() );
432 mLegacyPayload.reset( p.release() );
436 void Item::setPayloadBaseV2(
int spid,
int mtid, std::auto_ptr<PayloadBase> p )
438 d_func()->setPayloadBaseImpl( spid, mtid, p,
false );
441 void Item::addPayloadBaseVariant(
int spid,
int mtid, std::auto_ptr<PayloadBase> p )
const
443 d_func()->setPayloadBaseImpl( spid, mtid, p,
true );
455 result.reserve( d->mPayloads.size() );
457 for ( PayloadContainer::const_iterator it = d->mPayloads.begin(), end = d->mPayloads.end() ; it != end ; ++it ) {
458 result.insert( std::upper_bound( result.begin(), result.end(), it->metaTypeId ), it->metaTypeId );
466 kDebug() <<
"mimeType() = " <<
mimeType() <<
"; other.mimeType() = " << other.
mimeType();
467 kDebug() <<
"id() = " <<
id() <<
"; other.id() = " << other.
id();
468 Q_ASSERT_X(
false,
"Item::apply",
"mimetype or id missmatch" );
480 QList<QByteArray> attrs;
483 attrs.append( attribute->
type() );
486 QMutableHashIterator<QByteArray, Attribute*> it( d_ptr->mAttributes );
487 while ( it.hasNext() ) {
489 if ( !attrs.contains( it.key() ) ) {
496 d_func()->resetChangeLog();
499 AKONADI_DEFINE_PRIVATE(
Item )