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 bool Item::hasPayload()
const
265 return d_func()->hasMetaTypeId( -1 );
268 KUrl Item::url( UrlType type )
const
271 url.setProtocol( QString::fromLatin1(
"akonadi" ) );
272 url.addQueryItem( QLatin1String(
"item" ), QString::number(
id() ) );
274 if ( type == UrlWithMimeType ) {
275 url.addQueryItem( QLatin1String(
"type" ), mimeType() );
281 Item Item::fromUrl(
const KUrl &url )
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 );
446 QSet<QByteArray> Item::cachedPayloadParts()
const
449 return d->mCachedPayloadParts;
452 void Item::setCachedPayloadParts(
const QSet< QByteArray > &cachedParts)
455 d->mCachedPayloadParts = cachedParts;
458 QSet<QByteArray> Item::availablePayloadParts()
const
463 QVector<int> Item::availablePayloadMetaTypeIds()
const
467 result.reserve( d->mPayloads.size() );
469 for ( PayloadContainer::const_iterator it = d->mPayloads.begin(), end = d->mPayloads.end() ; it != end ; ++it ) {
470 result.insert( std::upper_bound( result.begin(), result.end(), it->metaTypeId ), it->metaTypeId );
475 void Item::apply(
const Item &other )
477 if ( mimeType() != other.mimeType() || id() != other.id() ) {
478 kDebug() <<
"mimeType() = " << mimeType() <<
"; other.mimeType() = " << other.mimeType();
479 kDebug() <<
"id() = " << id() <<
"; other.id() = " << other.id();
480 Q_ASSERT_X(
false,
"Item::apply",
"mimetype or id missmatch" );
483 setRemoteId( other.remoteId() );
484 setRevision( other.revision() );
485 setRemoteRevision( other.remoteRevision() );
486 setFlags( other.flags() );
487 setModificationTime( other.modificationTime() );
488 setSize( other.size() );
489 setParentCollection( other.parentCollection() );
490 setStorageCollectionId( other.storageCollectionId() );
492 QList<QByteArray> attrs;
493 foreach (
Attribute *attribute, other.attributes() ) {
494 addAttribute( attribute->
clone() );
495 attrs.append( attribute->
type() );
498 QMutableHashIterator<QByteArray, Attribute*> it( d_ptr->mAttributes );
499 while ( it.hasNext() ) {
501 if ( !attrs.contains( it.key() ) ) {
508 d_func()->resetChangeLog();
511 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.