phonebookengines/VirtualPhonebook/VPbkSimStoreImpl/src/CMultipleReadCmd.cpp
branchRCL_3
changeset 20 f4a778e096c2
parent 0 e686773b3f54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/VirtualPhonebook/VPbkSimStoreImpl/src/CMultipleReadCmd.cpp	Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,454 @@
+/*
+* Copyright (c) 2002-2007 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:  A class that can read multiple contacts from ETel store
+*                Uses ETel RMobilePhoneBookStore Read
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "CMultipleReadCmd.h"
+
+#include "CVPbkETelCntConverter.h"
+#include "CVPbkSimContactBuf.h"
+#include "CVPbkSimCntField.h"
+#include "VPbkSimStoreImplError.h"
+#include "CBasicStore.h"
+#include "CContactArray.h"
+#include "VPbkDebug.h"
+
+namespace VPbkSimStoreImpl {
+
+// CONSTANTS
+
+// Define some default size of one contact for buffer creation
+const TInt KDefaultSizeForOneContact = 256;
+// Define a maximum size for the read buffer. 20 contacts at one request is
+// a pretty good base for maximum.
+const TInt KMaxSizeForBuffer = 20 * KDefaultSizeForOneContact;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+namespace {
+// -----------------------------------------------------------------------------
+// Return the number of indexes
+// -----------------------------------------------------------------------------
+//
+inline TInt AmountOfIndexes( TInt aLastIndex, TInt aFirstIndex )
+    {
+    return aLastIndex - aFirstIndex + 1;
+    }
+} // unnamed namespace
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::CMultipleReadCmd
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CMultipleReadCmd::CMultipleReadCmd( CBasicStore& aBasicStore, 
+        TInt aFirstIndexToRead, TInt aLastIndexToRead )
+        :   CActive( EPriorityStandard ),
+            iBasicStore( aBasicStore ),
+            iFirstIndexToRead( aFirstIndexToRead ),
+            iLastIndexToRead( aLastIndexToRead ),
+            iIndexToRead( KVPbkSimStoreInvalidETelIndex ),
+            iBufferPtr( 0, NULL )
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::CMultipleReadCmd
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CMultipleReadCmd::CMultipleReadCmd( CBasicStore& aBasicStore, 
+        TInt& aIndexToRead )
+        :   CActive( EPriorityStandard ),
+            iBasicStore( aBasicStore ),
+            iFirstIndexToRead( KVPbkSimStoreInvalidETelIndex ),
+            iLastIndexToRead( KVPbkSimStoreInvalidETelIndex ),
+            iIndexToRead( aIndexToRead ),
+            iBufferPtr( 0, NULL )
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::ConstructL()
+    {
+    iCntConverter = CVPbkETelCntConverter::NewL();
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CMultipleReadCmd* CMultipleReadCmd::NewLC( CBasicStore& aBasicStore )
+    {
+    CMultipleReadCmd* self = new( ELeave ) CMultipleReadCmd( aBasicStore, 
+        KVPbkSimStoreFirstETelIndex, KVPbkSimStoreInvalidETelIndex );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CMultipleReadCmd* CMultipleReadCmd::NewLC( CBasicStore& aBasicStore,    
+        TInt aFirstIndexToRead, TInt aLastIndexToRead )
+    {
+    CMultipleReadCmd* self = new( ELeave ) CMultipleReadCmd( aBasicStore, 
+            aFirstIndexToRead, aLastIndexToRead );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CMultipleReadCmd* CMultipleReadCmd::NewLC( CBasicStore& aBasicStore, 
+        TInt& aIndexToRead )
+    {
+    CMultipleReadCmd* self = new( ELeave ) CMultipleReadCmd( aBasicStore, 
+        aIndexToRead );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+    
+// Destructor
+CMultipleReadCmd::~CMultipleReadCmd()
+    {
+    CancelCmd();
+    delete iCntConverter;
+    delete iBuffer;
+    iCntArray.ResetAndDestroy();
+    iCntArray.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::Execute
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::Execute()
+    {
+    __ASSERT_DEBUG( iObserver,
+        VPbkSimStoreImpl::Panic( EPreCondCMultipleReadCmdExecute ) );
+        
+    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+        "VPbkSimStoreImpl: CMultipleReadCmd::Execute Request") );        
+        
+    if ( iIndexToRead != KVPbkSimStoreInvalidETelIndex )
+        {
+        iFirstIndexToRead = iIndexToRead;
+        iLastIndexToRead = iIndexToRead;
+        }
+    else if ( iLastIndexToRead == KVPbkSimStoreInvalidETelIndex )
+        {
+        iLastIndexToRead = iBasicStore.ETelStoreInfo().iTotalEntries;
+        }
+
+    // Define the size of the buffer. ETel iTotalEntries can not be trusted.
+    TInt amountOfIndexes = 
+        AmountOfIndexes( iLastIndexToRead, iFirstIndexToRead );
+    if ( amountOfIndexes > 0 )
+        {
+        // Create a buffer according to amount of possible contacts to read.
+        // There must be a limit for the size.
+        TInt size = Min( KMaxSizeForBuffer, 
+            amountOfIndexes * KDefaultSizeForOneContact );
+        TRAPD( result, iBuffer = HBufC8::NewL( size ) );
+        if ( result != KErrNone )
+            {
+            DoDummyRequest( result );
+            }
+        else
+            {
+            iBufferPtr.Set( iBuffer->Des() );
+            DoRequest();
+            }
+        }
+    else
+        {
+        // There was probably a problem with ETel iTotalEntries.
+        // Behave same as iTotalEntries would be zero. Completing with
+        // KErrNotFound from ETel means that there were no contacts
+        // in given index range.
+        DoDummyRequest( KErrNotFound );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::AddObserverL
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::AddObserverL( MVPbkSimCommandObserver& aObserver )
+    {
+    __ASSERT_DEBUG( !iObserver,
+        VPbkSimStoreImpl::Panic( EPreCondCMultipleReadCmdAddObserverL ) );
+    iObserver = &aObserver;
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::CancelCmd
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::CancelCmd()
+    {
+    CActive::Cancel();
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::RunL
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::RunL()
+    {
+    TInt result = iStatus.Int();
+
+    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+        "VPbkSimStoreImpl: RMobilePhoneBooStore::Read h%d complete %d"),
+        iBasicStore.ETelStore().SubSessionHandle(), result);
+
+    switch ( result )
+        {
+        case KErrNone:
+            {
+            // Convert from ETel to own contacts
+            ConvertContactsL();
+            // Check that was the buffer big enough
+            if ( WasBufferBigEnough() )
+                {
+                // Contacts were found -> update contact array
+                UpdateContactArrayL();
+                }
+            // Buffer wasn't big enough -> Check that it's not growing
+            // for ever.
+            else if ( !IsBufferSizeInSane() )
+                {
+                // Make buffer bigger and read again
+                EnlargeBufferL();
+                }
+            else
+                {
+                // Stop trying -> there is something wrong in ETel 
+                result = KErrOverflow;
+                }
+            
+            // Stop if error
+            if ( result != KErrNone )
+                {
+                iObserver->CommandError( *this, result );
+                }
+            // If all the indexes have been read and we are done.
+            else if ( AmountOfIndexes( 
+                        iLastIndexToRead, iFirstIndexToRead ) <= 0 )
+                {
+                iObserver->CommandDone( *this );
+                }
+            // There are still contacts to read
+            else
+                {
+                DoRequest();
+                }
+            break;
+            }
+        case KErrNotFound:
+            {
+            // If nothing found update the array and complete command.
+            iBasicStore.Contacts().Delete( iFirstIndexToRead, iLastIndexToRead );
+            iObserver->CommandDone( *this );
+            break;
+            }
+        default:
+            {
+            iObserver->CommandError( *this, result );
+            break;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::DoCancel
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::DoCancel()
+    {
+    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+        "VPbkSimStoreImpl: RMobilePhoneBooStore::Read h%d Cancel"),
+        iBasicStore.ETelStore().SubSessionHandle());
+    iBasicStore.ETelStore().CancelAsyncRequest( EMobilePhoneStoreRead );
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::RunError
+// -----------------------------------------------------------------------------
+//
+TInt CMultipleReadCmd::RunError( TInt aError )
+    {
+    iObserver->CommandError( *this, aError );
+    return KErrNone;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::DoDummyRequest
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::DoDummyRequest( TInt aResult )
+    {
+    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+        "VPbkSimStoreImpl: CMultipleReadCmd dummy request"));
+    TRequestStatus* status = &iStatus;
+    User::RequestComplete( status, aResult );
+    SetActive();
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::DoRequest
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::DoRequest()
+    {
+    ResetBuffer();
+
+    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+        "VPbkSimStoreImpl: RMobilePhoneBooStore::Read h%d request\
+        firstslot=%d,lastslot=%d"),
+        iBasicStore.ETelStore().SubSessionHandle(),
+        iFirstIndexToRead, iLastIndexToRead);
+
+    iBasicStore.ETelStore().Read( iStatus, iFirstIndexToRead, 
+        AmountOfIndexes( iLastIndexToRead, iFirstIndexToRead ), iBufferPtr );
+    SetActive();
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::IsBufferSizeInSane
+// -----------------------------------------------------------------------------
+//
+TBool CMultipleReadCmd::IsBufferSizeInSane()
+    {
+    __ASSERT_DEBUG( iBuffer, 
+        Panic( EPreCond_CMultipleReadCmd_IsBufferSizeInSane ) );
+        
+    if ( iBuffer->Size() >= KMaxSizeForBuffer )
+        {
+        return ETrue;
+        }
+    return EFalse;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::EnlargeBufferL
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::EnlargeBufferL()
+    {
+    __ASSERT_DEBUG( iBuffer, 
+        Panic( EPreCond_CMultipleReadCmd_EnlargeBufferL ) );
+        
+    const TInt doubleFactor = 2;
+    TInt newSize = iBufferPtr.MaxSize() * doubleFactor;
+    
+    HBufC8* buffer = HBufC8::NewL( newSize );
+    delete iBuffer;
+    iBuffer = buffer;
+    iBufferPtr.Set( iBuffer->Des() );
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::ConvertContactsL
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::ConvertContactsL()
+    {    
+    // Make sure that there are no old contacts
+    iCntArray.ResetAndDestroy();
+    
+    if ( iBufferPtr.Length() > 0 )
+        {
+        iCntConverter->ConvertFromETelToVPbkSimContactsL( 
+            iCntArray, iBufferPtr, iBasicStore );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::WasBufferBigEnough
+// -----------------------------------------------------------------------------
+//
+TBool CMultipleReadCmd::WasBufferBigEnough()
+    {
+    // ConvertContactsL must be called before this. The logic is that if
+    // ETel retuned KErrNone from Read request but there are not contacts
+    // in iBuffer then the buffer was too small.
+    return iCntArray.Count() > 0;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::UpdateContactArrayL
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::UpdateContactArrayL()
+    {
+    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
+        "VPbkSimStoreImpl: CMultipleReadCmd::UpdateContactArrayL "));
+    
+    __ASSERT_DEBUG( iCntArray.Count() > 0, Panic( EReadingFromETelFailed ) );
+
+    // Get amount of contacts
+    TInt cntCount = iCntArray.Count();
+    for ( TInt i = cntCount - 1; i >= 0; --i )
+        {
+        // Check the biggest sim index that was read
+        TInt simIndex = iCntArray[i]->SimIndex();
+        if ( simIndex >= iFirstIndexToRead )
+            {
+            // iFirstIndexToRead must be the first sim index that was not read.
+            iFirstIndexToRead = simIndex + 1; 
+            }
+
+        // Add contacts to contact array. Ownership changes.
+        iBasicStore.Contacts().AddOrReplaceL( iCntArray[i] );
+        iCntArray.Remove( i );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMultipleReadCmd::ResetBuffer
+// -----------------------------------------------------------------------------
+//
+void CMultipleReadCmd::ResetBuffer()
+    {
+    iBufferPtr.FillZ( iBufferPtr.MaxLength() );
+    iBufferPtr.Zero();
+    }
+} // namespace VPbkSimStoreImpl
+//  End of File