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 QSet<QByteArray> Item::loadedPayloadParts()
 const 
  203 QByteArray Item::payloadData()
 const 
  211 void Item::setPayloadFromData( 
const QByteArray &data )
 
  216 void Item::clearPayload()
 
  218   d_func()->mClearPayload = 
true;
 
  221 int Item::revision()
 const 
  223   return d_func()->mRevision;
 
  226 void Item::setRevision( 
int rev )
 
  228   d_func()->mRevision = rev;
 
  233   return d_func()->mCollectionId;
 
  236 void Item::setStorageCollectionId( 
Entity::Id collectionId )
 
  238   d_func()->mCollectionId = collectionId;
 
  241 QString Item::mimeType()
 const 
  243   return d_func()->mMimeType;
 
  246 void Item::setSize( qint64 size )
 
  250   d->mSizeChanged = 
true;
 
  253 qint64 Item::size()
 const 
  255   return d_func()->mSize;
 
  258 void Item::setMimeType( 
const QString & mimeType )
 
  260   d_func()->mMimeType = mimeType;
 
  263 void Item::setGid( 
const QString &
id )
 
  268 QString Item::gid()
 const 
  270   return d_func()->mGid;
 
  273 bool Item::hasPayload()
 const 
  275   return d_func()->hasMetaTypeId( -1 );
 
  278 KUrl Item::url( UrlType type )
 const 
  281   url.setProtocol( QString::fromLatin1( 
"akonadi" ) );
 
  282   url.addQueryItem( QLatin1String( 
"item" ), QString::number( 
id() ) );
 
  284   if ( type == UrlWithMimeType ) {
 
  285     url.addQueryItem( QLatin1String( 
"type" ), mimeType() );
 
  291 Item Item::fromUrl( 
const KUrl &url )
 
  293   if ( url.protocol() != QLatin1String( 
"akonadi" ) ) {
 
  297   const QString itemStr = url.queryItem( QLatin1String( 
"item" ) );
 
  299   Item::Id itemId = itemStr.toLongLong( &ok );
 
  304   return Item( itemId );
 
  311 Q_GLOBAL_STATIC( Payload<Dummy>, dummyPayload )
 
  313 PayloadBase* Item::payloadBase()
 const 
  316   d->tryEnsureLegacyPayload();
 
  317   if ( d->mLegacyPayload ) {
 
  318     return d->mLegacyPayload.get();
 
  320     return dummyPayload();
 
  324 void ItemPrivate::tryEnsureLegacyPayload()
 const 
  326   if ( !mLegacyPayload ) {
 
  327     for ( PayloadContainer::const_iterator it = mPayloads.begin(), end = mPayloads.end() ; it != end ; ++it ) {
 
  328       if ( lookupLegacyMapping( mMimeType, it->payload.get() ) ) {
 
  329           mLegacyPayload = it->payload; 
 
  335 PayloadBase* Item::payloadBaseV2( 
int spid, 
int mtid )
 const 
  337   return d_func()->payloadBaseImpl( spid, mtid );
 
  341     class ConversionGuard {
 
  345         explicit ConversionGuard( 
bool & b )
 
  356 bool Item::ensureMetaTypeId( 
int mtid )
 const 
  360   if ( d->mPayloads.empty() ) {
 
  365   if ( d->hasMetaTypeId( mtid ) ) {
 
  371   if ( d->mConversionInProgress ) {
 
  377     const ConversionGuard guard( d->mConversionInProgress );
 
  379     return d->movePayloadFrom( converted.d_func(), mtid );
 
  380   } 
catch ( 
const std::exception & e ) {
 
  381     kDebug() << 
"conversion threw:" << e.what();
 
  384     kDebug() << 
"conversion threw something not derived from std::exception: fix the program!";
 
  389 static QString format_type( 
int spid, 
int mtid ) {
 
  390   return QString::fromLatin1( 
"sp(%1)<%2>" )
 
  391       .arg( spid ).arg( QLatin1String( QMetaType::typeName( mtid ) ) );
 
  394 static QString format_types( 
const PayloadContainer & c ) {
 
  396   for ( PayloadContainer::const_iterator it = c.begin(), end = c.end() ; it != end ; ++it ) {
 
  397     result.push_back( format_type( it->sharedPointerId, it->metaTypeId ) );
 
  399   return result.join( QLatin1String( 
", " ) );
 
  403 QString Item::payloadExceptionText( 
int spid, 
int mtid )
 const 
  406   if ( d->mPayloads.empty() ) {
 
  407     return QLatin1String( 
"No payload set" );
 
  409     return QString::fromLatin1( 
"Wrong payload type (requested: %1; present: %2" )
 
  410         .arg( format_type( spid, mtid ), format_types( d->mPayloads ) );
 
  414 void Item::throwPayloadException( 
int spid, 
int mtid )
 const 
  417   if ( d->mPayloads.empty() ) {
 
  418     throw PayloadException( 
"No payload set" );
 
  420     throw PayloadException( QString::fromLatin1( 
"Wrong payload type (requested: %1; present: %2" )
 
  421                             .arg( format_type( spid, mtid ), format_types( d->mPayloads ) ) );
 
  426 void Item::setPayloadBase( PayloadBase* p )
 
  428   d_func()->setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase>( p ) );
 
  431 void ItemPrivate::setLegacyPayloadBaseImpl( std::auto_ptr<PayloadBase> p )
 
  433   if ( 
const shared_ptr<
const std::pair<int,int> > pair = lookupLegacyMapping( mMimeType, p.get() ) ) {
 
  434     std::auto_ptr<PayloadBase> clone;
 
  436       clone.reset( p->clone() );
 
  438     setPayloadBaseImpl( pair->first, pair->second, p, 
false );
 
  439     mLegacyPayload.reset( clone.release() );
 
  442     mLegacyPayload.reset( p.release() );
 
  446 void Item::setPayloadBaseV2( 
int spid, 
int mtid, std::auto_ptr<PayloadBase> p )
 
  448   d_func()->setPayloadBaseImpl( spid, mtid, p, 
false );
 
  451 void Item::addPayloadBaseVariant( 
int spid, 
int mtid, std::auto_ptr<PayloadBase> p )
 const 
  453   d_func()->setPayloadBaseImpl( spid, mtid, p, 
true );
 
  456 QSet<QByteArray> Item::cachedPayloadParts()
 const 
  459   return d->mCachedPayloadParts;
 
  462 void Item::setCachedPayloadParts(
const QSet< QByteArray > &cachedParts)
 
  465   d->mCachedPayloadParts = cachedParts;
 
  468 QSet<QByteArray> Item::availablePayloadParts()
 const 
  473 QVector<int> Item::availablePayloadMetaTypeIds()
 const 
  477   result.reserve( d->mPayloads.size() );
 
  479   for ( PayloadContainer::const_iterator it = d->mPayloads.begin(), end = d->mPayloads.end() ; it != end ; ++it ) {
 
  480       result.insert( std::upper_bound( result.begin(), result.end(), it->metaTypeId ), it->metaTypeId );
 
  485 void Item::apply( 
const Item &other )
 
  487   if ( mimeType() != other.mimeType() || id() != other.id() ) {
 
  488     kDebug() << 
"mimeType() = " << mimeType() << 
"; other.mimeType() = " << other.mimeType();
 
  489     kDebug() << 
"id() = " << id() << 
"; other.id() = " << other.id();
 
  490     Q_ASSERT_X( 
false, 
"Item::apply", 
"mimetype or id missmatch" );
 
  493   setRemoteId( other.remoteId() );
 
  494   setRevision( other.revision() );
 
  495   setRemoteRevision( other.remoteRevision() );
 
  496   setFlags( other.flags() );
 
  497   setModificationTime( other.modificationTime() );
 
  498   setSize( other.size() );
 
  499   setParentCollection( other.parentCollection() );
 
  500   setStorageCollectionId( other.storageCollectionId() );
 
  502   QList<QByteArray> attrs;
 
  503   foreach ( 
Attribute *attribute, other.attributes() ) {
 
  504     addAttribute( attribute->
clone() );
 
  505     attrs.append( attribute->
type() );
 
  508   QMutableHashIterator<QByteArray, Attribute*> it( d_ptr->mAttributes );
 
  509   while ( it.hasNext() ) {
 
  511     if ( !attrs.contains( it.key() ) ) {
 
  518   d_func()->resetChangeLog();
 
  521 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.