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.