00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef AKONADI_PROTOCOLHELPER_P_H
00021 #define AKONADI_PROTOCOLHELPER_P_H
00022
00023 #include <akonadi/cachepolicy.h>
00024 #include <akonadi/collection.h>
00025 #include <akonadi/collectionutils_p.h>
00026 #include <akonadi/item.h>
00027 #include <akonadi/itemfetchscope.h>
00028
00029 #include <akonadi/private/imapparser_p.h>
00030 #include <akonadi/private/protocol_p.h>
00031
00032 #include <boost/bind.hpp>
00033 #include <algorithm>
00034
00035 namespace Akonadi {
00036
00045 class ProtocolHelper
00046 {
00047 public:
00049 enum PartNamespace {
00050 PartGlobal,
00051 PartPayload,
00052 PartAttribute
00053 };
00054
00062 static int parseCachePolicy( const QByteArray &data, CachePolicy &policy, int start = 0 );
00063
00067 static QByteArray cachePolicyToByteArray( const CachePolicy &policy );
00068
00072 static void parseAncestors( const QByteArray &data, Entity *entity, int start = 0 );
00073
00081 static int parseCollection( const QByteArray &data, Collection &collection, int start = 0 );
00082
00086 static QByteArray attributesToByteArray( const Entity &entity, bool ns = false );
00087
00091 static QByteArray encodePartIdentifier( PartNamespace ns, const QByteArray &label, int version = 0 );
00092
00096 static QByteArray decodePartIdentifier( const QByteArray &data, PartNamespace &ns );
00097
00102 template <typename T>
00103 static QByteArray entitySetToByteArray( const QList<T> &_objects, const QByteArray &command )
00104 {
00105 if ( _objects.isEmpty() )
00106 throw Exception( "No objects specified" );
00107
00108 typename T::List objects( _objects );
00109
00110 QByteArray rv;
00111 std::sort( objects.begin(), objects.end(), boost::bind( &T::id, _1 ) < boost::bind( &T::id, _2 ) );
00112 if ( objects.first().isValid() ) {
00113
00114 rv += " " AKONADI_CMD_UID " ";
00115 if ( !command.isEmpty() ) {
00116 rv += command;
00117 rv += ' ';
00118 }
00119 QList<typename T::Id> uids;
00120 foreach ( const T &object, objects )
00121 uids << object.id();
00122 ImapSet set;
00123 set.add( uids );
00124 rv += set.toImapSequenceSet();
00125 return rv;
00126 }
00127
00128
00129 if ( std::find_if( objects.constBegin(), objects.constEnd(),
00130 boost::bind( &QString::isEmpty, boost::bind( &T::remoteId, _1 ) ) )
00131 != objects.constEnd() )
00132 {
00133 throw Exception( "No remote identifier specified" );
00134 }
00135
00136
00137 if ( std::find_if( objects.constBegin(), objects.constEnd(),
00138 !boost::bind( static_cast<bool (*)(const T&)>( &CollectionUtils::hasValidHierarchicalRID ), _1 ) )
00139 == objects.constEnd() && objects.size() == 1 )
00140 {
00141
00142 rv += " " AKONADI_CMD_HRID " ";
00143 if ( !command.isEmpty() ) {
00144 rv += command;
00145 rv += ' ';
00146 }
00147 rv += '(' + hierarchicalRidToByteArray( objects.first() ) + ')';
00148 return rv;
00149 }
00150
00151
00152 QList<QByteArray> rids;
00153 foreach ( const T &object, objects ) {
00154 rids << ImapParser::quote( object.remoteId().toUtf8() );
00155 }
00156
00157 rv += " " AKONADI_CMD_RID " ";
00158 if ( !command.isEmpty() ) {
00159 rv += command;
00160 rv += ' ';
00161 }
00162 rv += '(';
00163 rv += ImapParser::join( rids, " " );
00164 rv += ')';
00165 return rv;
00166 }
00167
00172 template <typename T>
00173 static QByteArray entityIdToByteArray( const T &object, const QByteArray &command )
00174 {
00175 return entitySetToByteArray( typename T::List() << object, command );
00176 }
00177
00182 static QByteArray hierarchicalRidToByteArray( const Collection &col );
00183
00188 static QByteArray hierarchicalRidToByteArray( const Item &item );
00189
00193 static QByteArray itemFetchScopeToByteArray( const ItemFetchScope &fetchScope );
00194
00198 static void parseItemFetchResult( const QList<QByteArray> &lineTokens, Item &item );
00199 };
00200
00201 }
00202
00203 #endif