diff -r 000000000000 -r 8466d47a6819 emailservices/emailclientapi/src/messageiterator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emailservices/emailclientapi/src/messageiterator.cpp Thu Dec 17 08:39:21 2009 +0200 @@ -0,0 +1,316 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: This file implements class CMessageIterator. +* +*/ + +#include "emailmessage.h" +#include "messageiterator.h" +#include "emailapiutils.h" +#include "CFSMailPlugin.h" +#include "emailapiutils.h" +#include "emailclientapi.hrh" +#include "MFSMailIterator.h" + +// number of messages in chunk to retrive from protocol plugin. Actual chunk +// size is one less because last element is used for reference to next chunk +// retrieval. See ReadNextChunkL() for details. +const TInt KMessageChunkSize = 5; + +const TInt KUndefined = -1; +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CMessageIterator* CMessageIterator::NewL( + MFSMailIterator* aIterator, + CPluginData& aPluginData, + TUint aCount ) + { + CMessageIterator* iter = new ( ELeave ) + CMessageIterator( aIterator, aPluginData, aCount ); + return iter; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CMessageIterator::~CMessageIterator() + { + iPluginData.ReleaseInstance(); + TInt count = iMessageArray.Count(); + iMessageArray.ResetAndDestroy(); + for (TInt i = count; i < iFsMessageArray.Count(); i++) + { + delete iFsMessageArray[i]; + } + iFsMessageArray.Reset(); + delete iIterator; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +TEmailTypeId CMessageIterator::InterfaceId() const + { + return KEmailIFUidMessageIterator; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void CMessageIterator::Release() + { + delete this; + } + +// ----------------------------------------------------------------------------- +// Returns next message +// Messages are retrieved from protocol plugin in chunks of x messages and +// when NextL has be called for x times, next chunk is retrieved. This +// is trade-off between RAM consumption and speed. +// ----------------------------------------------------------------------------- +MEmailMessage* CMessageIterator::NextL() + { + if ( iCursor == KUndefined ) + { + // Buffer empty, read the first chunk + if ( !ReadNextChunkL() ) + { + // No messages found, + // Reset the cursor and return NULL + iCursor = KUndefined; + iStartMsgId = TFSMailMsgId(); + return NULL; + } + // Items found, return the first item in the buffer + iCursor = 0; + } + else + { + // Iterate to the next item + iCursor++; + } + return ReadFromChunkL(); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +MEmailMessage* CMessageIterator::PreviousL() + { + if ( iCursor == KUndefined ) + { + iStartMsgId = TFSMailMsgId(); + // Buffer empty, client should first call NextL + return NULL; + } + // Iterate to the previous item + iCursor--; + return ReadFromChunkL(); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +TBool CMessageIterator::ReadNextChunkL( ) + { + TBool chunkFound = EFalse; + + // Delete previous items if exist + CleanCache(); + iHasMoreNextItems = iIterator->NextL( + iStartMsgId, + KMessageChunkSize, + iFsMessageArray ); + if ( iFsMessageArray.Count() > 0) + { + chunkFound = ETrue; + // Set the cursor to the first item + iCursor = 0; + iHasMorePrevItems = ETrue; + } + return chunkFound; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +TBool CMessageIterator::ReadPreviousChunkL( ) + { + TBool chunkFound = EFalse; + + // Delete previous items if exist + CleanCache(); + RPointerArray tmp; + iHasMorePrevItems = iIterator->PreviousL( + iStartMsgId, + KMessageChunkSize, + tmp ); + TInt count = tmp.Count(); + if ( count > 0) + { + // It seems that items have been found + // Set the cursor to the end of array + iCursor = count - 1; + iHasMoreNextItems = ETrue; + chunkFound = ETrue; + // Revise the order of the buffer. + // Create complete cache, so it is easier to iterate, + // as now we have to start from the end of cache + for (TInt i = count; i > 0; i--) + { + CFSMailMessage* msg = tmp[i-1]; + iFsMessageArray.AppendL( msg ); + AddToCacheL( msg ); + } + } + + return chunkFound; + } + + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +MEmailMessage* CMessageIterator::ReadFromChunkL() + { + if ( iCursor >= KMessageChunkSize ) + { + if ( iHasMoreNextItems ) + { + iStartMsgId = iFsMessageArray[iCursor-1]->GetMessageId(); + if ( !ReadNextChunkL() ) + { + // No more items found, + // set the cursor to the previous item, + // and return NULL. + iCursor--; + return NULL; + } + } + else + { + // No more items found, + // set the cursor to the previous item, + // and return NULL. + iCursor--; + return NULL; + } + } + else if ( iCursor < 0 ) + { + iStartMsgId = iFsMessageArray[0]->GetMessageId(); + if ( iHasMorePrevItems ) + { + if ( !ReadPreviousChunkL() ) + { + // Buffer is empty now, client should call nextL, + // and start reading from the start of the buffer + iCursor = KUndefined; + return NULL; + } + } + else + { + // Buffer is empty now, client should call nextL, + // and start reading from the start of the buffer + iCursor = KUndefined; + return NULL; + } + } + + if ( iCursor < iFsMessageArray.Count() ) + { + /* There are items to read in the cache */ + if ( iCursor >= iMessageArray.Count() ) + { + AddToCacheL( iFsMessageArray[iCursor] ); + } + return iMessageArray[iCursor]; + } + else + { + // No more items found, + // set the cursor to the previous item, + // and return NULL. + iCursor--; + return NULL; + } + } + + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void CMessageIterator::AddToCacheL( CFSMailMessage* aFsMsg ) + { + CEmailMessage* message = CEmailMessage::NewL( iPluginData, aFsMsg, EAPIOwns ); + iMessageArray.AppendL(message); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void CMessageIterator::CleanCache() + { + // This is strange loop indeed + // Both arrays has items that are deleted, iMessageArray has objects that point to iFsMessageArray + // Index in both arrays goes syncronously + // To prevent double destruction, first delete iMessageArray onjects and then the rest of the iFsMessageArray + TInt count = iMessageArray.Count(); + iMessageArray.ResetAndDestroy(); + for (TInt i = count; i < iFsMessageArray.Count(); i++) + { + iFsMessageArray.Remove(count); + } + iFsMessageArray.Reset(); + } +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +TUint CMessageIterator::Count() const + { + return iCount; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void CMessageIterator::ConstructL() + { + iPlugin = iPluginData.ClaimInstanceL(); + + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CMessageIterator::CMessageIterator( + MFSMailIterator* aIterator, + CPluginData& aPluginData, + TUint aCount ) : + iIterator( aIterator ), + iPluginData( aPluginData ), + iStartMsgId( TFSMailMsgId() ), + iState( EReadNextMessageChunk ), + iFsMessageArray( KMessageChunkSize ), + iCount( aCount ), + iCursor ( KUndefined ), + iFirstMsgId( TFSMailMsgId() ), + iHasMoreNextItems( ETrue ), + iHasMorePrevItems( ETrue ) + { + } + +// End of file.