--- /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