emailservices/emailclientapi/src/messageiterator.cpp
changeset 0 8466d47a6819
child 8 e1b6206813b4
--- /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<CFSMailMessage> 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.