Akonadi
create.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "create.h"
00020
00021 #include <QtCore/QDebug>
00022 #include <QtCore/QStringList>
00023
00024 #include "akonadi.h"
00025 #include "akonadiconnection.h"
00026 #include "storage/datastore.h"
00027 #include "storage/entity.h"
00028 #include "storage/transaction.h"
00029 #include "handlerhelper.h"
00030 #include "storage/selectquerybuilder.h"
00031
00032 #include "response.h"
00033 #include "libs/imapparser_p.h"
00034 #include "imapstreamparser.h"
00035
00036 using namespace Akonadi;
00037
00038 Create::Create( Scope::SelectionScope scope ) :
00039 Handler(),
00040 m_scope( scope )
00041 {
00042 }
00043
00044 bool Create::parseStream()
00045 {
00046 QString name = m_streamParser->readUtf8String();
00047 if ( name.isEmpty() )
00048 return failureResponse( "Invalid collection name" );
00049
00050 bool ok = false;
00051 Collection parent;
00052
00053 if ( m_scope == Scope::Uid || m_scope == Scope::None ) {
00054 qint64 parentId = m_streamParser->readNumber( &ok );
00055 if ( !ok ) {
00056 QString parentPath;
00057 int index = name.lastIndexOf( QLatin1Char('/') );
00058 if ( index > 0 ) {
00059 parentPath = name.left( index );
00060 name = name.mid( index + 1 );
00061 parent = HandlerHelper::collectionFromIdOrName( parentPath.toUtf8() );
00062 } else
00063 parentId = 0;
00064 } else {
00065 if ( parentId > 0 )
00066 parent = Collection::retrieveById( parentId );
00067 }
00068
00069 if ( parentId != 0 && !parent.isValid() )
00070 return failureResponse( "Parent collection not found" );
00071 } else if ( m_scope == Scope::Rid ) {
00072 const QString rid = m_streamParser->readUtf8String();
00073 if ( rid.isEmpty() )
00074 throw HandlerException( "Empty parent remote identifier" );
00075 if ( !connection()->resourceContext().isValid() )
00076 throw HandlerException( "Invalid resource context" );
00077 SelectQueryBuilder<Collection> qb;
00078 qb.addValueCondition( Collection::remoteIdColumn(), Query::Equals, rid );
00079 qb.addValueCondition( Collection::resourceIdColumn(), Query::Equals, connection()->resourceContext().id() );
00080 if ( !qb.exec() )
00081 throw HandlerException( "Unable to execute collection query" );
00082 const Collection::List cols = qb.result();
00083 if ( cols.size() == 0 )
00084 throw HandlerException( "Parent collection not found" );
00085 else if ( cols.size() > 1 )
00086 throw HandlerException( "Parent collection is not unique" );
00087 parent = cols.first();
00088 }
00089
00090 qint64 resourceId = 0;
00091 MimeType::List parentContentTypes;
00092 if ( parent.isValid() ) {
00093
00094 parentContentTypes = parent.mimeTypes();
00095 bool found = false;
00096 foreach ( const MimeType &mt, parentContentTypes ) {
00097 if ( mt.name() == QLatin1String( "inode/directory" ) ) {
00098 found = true;
00099 break;
00100 }
00101 }
00102 if ( !found )
00103 return failureResponse( "Parent collection can not contain sub-collections" );
00104
00105
00106 resourceId = parent.resourceId();
00107 } else {
00108
00109 QString sessionId = QString::fromUtf8( connection()->sessionId() );
00110 Resource res = Resource::retrieveByName( sessionId );
00111 if ( !res.isValid() )
00112 return failureResponse( "Cannot create top-level collection" );
00113 resourceId = res.id();
00114 }
00115
00116 Collection collection;
00117 if ( parent.isValid() )
00118 collection.setParentId( parent.id() );
00119 collection.setName( name.toUtf8() );
00120 collection.setResourceId( resourceId );
00121
00122
00123 QList<QByteArray> attributes;
00124 QList<QByteArray> mimeTypes;
00125 QList< QPair<QByteArray, QByteArray> > userDefAttrs;
00126 bool mimeTypesSet = false;
00127 attributes = m_streamParser->readParenthesizedList();
00128 for ( int i = 0; i < attributes.count() - 1; i += 2 ) {
00129 const QByteArray key = attributes.at( i );
00130 const QByteArray value = attributes.at( i + 1 );
00131 if ( key == "REMOTEID" ) {
00132 collection.setRemoteId( QString::fromUtf8( value ) );
00133 } else if ( key == "REMOTEREVISION" ) {
00134 collection.setRemoteRevision( QString::fromUtf8( value ) );
00135 } else if ( key == "MIMETYPE" ) {
00136 ImapParser::parseParenthesizedList( value, mimeTypes );
00137 mimeTypesSet = true;
00138 } else if ( key == "CACHEPOLICY" ) {
00139 HandlerHelper::parseCachePolicy( value, collection );
00140 } else {
00141 userDefAttrs << qMakePair( key, value );
00142 }
00143 }
00144
00145 DataStore *db = connection()->storageBackend();
00146 Transaction transaction( db );
00147
00148 if ( !db->appendCollection( collection ) )
00149 return failureResponse( "Could not create collection" );
00150
00151 QStringList effectiveMimeTypes;
00152 if ( mimeTypesSet ) {
00153 foreach ( const QByteArray &b, mimeTypes )
00154 effectiveMimeTypes << QString::fromUtf8( b );
00155 } else {
00156 foreach ( const MimeType &mt, parentContentTypes )
00157 effectiveMimeTypes << mt.name();
00158 }
00159 if ( !db->appendMimeTypeForCollection( collection.id(), effectiveMimeTypes ) )
00160 return failureResponse( "Unable to append mimetype for collection." );
00161
00162
00163 typedef QPair<QByteArray,QByteArray> QByteArrayPair;
00164 foreach ( const QByteArrayPair &attr, userDefAttrs ) {
00165 if ( !db->addCollectionAttribute( collection, attr.first, attr.second ) )
00166 return failureResponse( "Unable to add collection attribute." );
00167 }
00168
00169 Response response;
00170 response.setUntagged();
00171
00172
00173 db->activeCachePolicy( collection );
00174 const QByteArray b = HandlerHelper::collectionToByteArray( collection );
00175 response.setString( b );
00176 emit responseAvailable( response );
00177
00178 if ( !transaction.commit() )
00179 return failureResponse( "Unable to commit transaction." );
00180
00181 return successResponse( "CREATE completed" );
00182 }
00183
00184 #include "create.moc"