--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/VirtualPhonebook/VPbkSimStore/src/CContact.cpp Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,556 @@
+/*
+* 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 contact adapter between VPbk framework and VPbkSimStoreImpl
+*
+*/
+
+
+// INCLUDES
+#include "CContact.h"
+
+#include "CContactStore.h"
+#include "CFieldTypeMappings.h"
+#include "CViewContact.h"
+#include "MVPbkContactObserver.h"
+#include "CSupportedFieldTypes.h"
+#include "CContactOperationCallback.h"
+#include "VPbkSimStoreError.h"
+
+#include <CVPbkAsyncOperation.h>
+#include <CVPbkContactLinkArray.h>
+#include <CVPbkSimContact.h>
+#include <MVPbkSimCntStore.h>
+#include <MVPbkContactViewBase.h>
+#include <MVPbkContactStoreProperties.h>
+#include <RVPbkStreamedIntArray.h>
+#include <TVPbkSimStoreProperty.h>
+#include <VPbkSimCntFieldTypes.hrh>
+#include <MVPbkSimStoreOperation.h>
+#include <VPbkError.h>
+#include <MVPbkStoreContactProperties.h>
+
+namespace {
+
+// MODULE DATA STRUCTURES
+enum TContactFlags
+ {
+ KNewContact = 1
+ };
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+MVPbkContactObserver::TContactOp ConvertContactOperation(
+ MVPbkSimContactObserver::TEvent aEvent )
+ {
+ MVPbkContactObserver::TContactOp op =
+ MVPbkContactObserver::EContactOperationUnknown;
+ switch ( aEvent )
+ {
+ case MVPbkSimContactObserver::EDelete:
+ {
+ op = MVPbkContactObserver::EContactDelete;
+ break;
+ }
+ case MVPbkSimContactObserver::ESave:
+ {
+ op = MVPbkContactObserver::EContactCommit;
+ break;
+ }
+ default:
+ {
+ op = MVPbkContactObserver::EContactOperationUnknown;
+ break;
+ }
+ }
+ return op;
+ }
+
+TInt MaxNumberOfFieldsInContact( TVPbkSimCntFieldType aType,
+ TVPbkUSimStoreProperty& aUsimProp )
+ {
+ TInt result = 0;
+ switch ( aType )
+ {
+ case EVPbkSimReading: // FALLTHROUGH
+ case EVPbkSimNickName: // FALLTHROUGH
+ case EVPbkSimName:
+ {
+ ++result; // only one name field can exist
+ break;
+ }
+ case EVPbkSimEMailAddress:
+ {
+ if (aUsimProp.iMaxNumOfEmails != KVPbkSimStorePropertyUndefined)
+ {
+ result = aUsimProp.iMaxNumOfEmails;
+ }
+ break;
+ }
+ case EVPbkSimGsmNumber: // FALLTHROUGH
+ case EVPbkSimAdditionalNumber:
+ {
+ ++result; // always at least one number
+ if ( aUsimProp.iMaxNumOfAnrs != KVPbkSimStorePropertyUndefined )
+ {
+ result += aUsimProp.iMaxNumOfAnrs;
+ }
+ break;
+ }
+ default:
+ {
+ // Do nothing
+ break;
+ }
+ }
+ return result;
+ }
+}
+
+namespace VPbkSimStore {
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CContact::CContact
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+inline CContact::CContact( CContactStore& aParentStore )
+: iParentStore( aParentStore )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+inline void CContact::ConstructL( CVPbkSimContact& aSimContact,
+ TBool aIsNewContact )
+ {
+ if ( aIsNewContact )
+ {
+ iFlags.Set( KNewContact );
+ }
+ iFields.SetContact( *this, aSimContact );
+ iAsyncOp = new( ELeave ) VPbkEngUtils::CVPbkAsyncOperation;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CContact* CContact::NewL( CContactStore& aParentStore,
+ CVPbkSimContact* aSimContact, TBool aIsNewContact )
+ {
+ CContact* self = new ( ELeave ) CContact( aParentStore );
+ CleanupStack::PushL(self);
+ self->ConstructL( *aSimContact, aIsNewContact );
+ CleanupStack::Pop( self );
+ // Take ownership after construction
+ self->iSimContact = aSimContact;
+ return self;
+ }
+
+// Destructor
+CContact::~CContact()
+ {
+ delete iStoreOperation;
+ delete iAsyncOp;
+ delete iSimContact;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::ParentObject
+// -----------------------------------------------------------------------------
+//
+MVPbkObjectHierarchy& CContact::ParentObject() const
+ {
+ return iParentStore;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::ConstFields
+// -----------------------------------------------------------------------------
+//
+const MVPbkStoreContactFieldCollection& CContact::Fields() const
+ {
+ return iFields;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::IsSame
+// -----------------------------------------------------------------------------
+//
+TBool CContact::IsSame( const MVPbkStoreContact& aOtherContact ) const
+ {
+ if ( &ParentStore() == &aOtherContact.ParentStore() )
+ {
+ const CContact& otherCnt = static_cast<const CContact&>( aOtherContact );
+ return otherCnt.SimContact().SimIndex() == iSimContact->SimIndex();
+ }
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::CreateLinkLC
+// -----------------------------------------------------------------------------
+//
+MVPbkContactLink* CContact::CreateLinkLC() const
+ {
+ return iParentStore.CreateLinkLC( iSimContact->SimIndex() );
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::DeleteL
+// -----------------------------------------------------------------------------
+//
+void CContact::DeleteL( MVPbkContactObserver& aObserver ) const
+ {
+ if ( iStoreOperation )
+ {
+ User::Leave( KErrInUse );
+ }
+
+ // From the client point of view the MVPbkStoreContact is constant but
+ // implementation needs a non const contact.
+ RVPbkStreamedIntArray indexArray;
+ CleanupClosePushL( indexArray );
+ indexArray.AppendIntL(iSimContact->SimIndex() );
+ iStoreOperation = iParentStore.NativeStore().DeleteL( indexArray,
+ const_cast<CContact&>(*this));
+ iObserver = &aObserver;
+ CleanupStack::PopAndDestroy(); // indexArray
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::MatchContactStore
+// -----------------------------------------------------------------------------
+//
+TBool CContact::MatchContactStore(const TDesC& aContactStoreUri) const
+ {
+ return iParentStore.MatchContactStore(aContactStoreUri);
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::MatchContactStoreDomain
+// -----------------------------------------------------------------------------
+//
+TBool CContact::MatchContactStoreDomain(const TDesC& aContactStoreDomain) const
+ {
+ return iParentStore.MatchContactStoreDomain(aContactStoreDomain);
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::CreateBookmarkLC
+// -----------------------------------------------------------------------------
+//
+MVPbkContactBookmark* CContact::CreateBookmarkLC() const
+ {
+ return iParentStore.CreateBookmarkLC( iSimContact->SimIndex() );
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::ParentStore
+// -----------------------------------------------------------------------------
+//
+MVPbkContactStore& CContact::ParentStore() const
+ {
+ return iParentStore;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::Fields
+// -----------------------------------------------------------------------------
+//
+MVPbkStoreContactFieldCollection& CContact::Fields()
+ {
+ return iFields;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::CreateFieldLC
+// -----------------------------------------------------------------------------
+//
+MVPbkStoreContactField* CContact::CreateFieldLC(
+ const MVPbkFieldType& aFieldType ) const
+ {
+ if ( !iParentStore.SupportedFieldTypes().ContainsSame( aFieldType ) )
+ {
+ // According to contact API the function must leave if
+ // the type is invalid
+ User::Leave( KErrNotSupported );
+ }
+ TVPbkSimCntFieldType simType =
+ iParentStore.FieldTypeMappings().Match( aFieldType );
+
+ __ASSERT_DEBUG( simType != EVPbkSimUnknownType,
+ VPbkSimStore::Panic( ESimFieldTypeNotFound ) );
+
+ if ( simType == EVPbkSimGsmNumber ||
+ simType == EVPbkSimAdditionalNumber )
+ {
+ // EVPbkSimGsmNumber and EVPbkSimAdditionalNumber maps to same
+ // VPbk field type. A sim contact can have only one EVPbkSimGsmNumber
+ // field type and possibly many EVPbkSimAdditionalNumber types
+ // depending on the USIM store.
+ // However, if SIM card doesn't support additional number it is allowed
+ // to create as many EVPbkSimGsmNumber fields as client wants. This
+ // is needed to enable temporary contacts that holds multiple numbers.
+ CVPbkSimContact::TFieldLookup lookup =
+ iSimContact->FindField( EVPbkSimGsmNumber );
+ if ( lookup.EndOfLookup() ||
+ !( iParentStore.SimStoreCapabilities() &
+ VPbkSimStoreImpl::KAdditionalNumUsed ))
+ {
+ simType = EVPbkSimGsmNumber;
+ }
+ else
+ {
+ simType = EVPbkSimAdditionalNumber;
+ }
+ }
+
+ CVPbkSimCntField* field = iSimContact->CreateFieldLC( simType );
+ TContactNewField* fieldWrapper = new( ELeave ) TContactNewField( field );
+ fieldWrapper->SetParentContact( const_cast<CContact&>( *this ) );
+ CleanupStack::Pop( field );
+ CleanupDeletePushL( fieldWrapper );
+ return fieldWrapper;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::AddFieldL
+// -----------------------------------------------------------------------------
+//
+TInt CContact::AddFieldL( MVPbkStoreContactField* aField )
+ {
+ __ASSERT_ALWAYS( aField, VPbkError::Panic( VPbkError::ENullContactField ) );
+ // Test that the client gives this contact's field and doesn't pass
+ // an existing field of this contact as a new one
+ __ASSERT_ALWAYS( &aField->ParentContact() == this &&
+ aField != iFields.FieldPointer(),
+ VPbkError::Panic( VPbkError::EInvalidContactField ) );
+
+ // Now the wrapper is casted back
+ TContactNewField* fieldWrapper = static_cast<TContactNewField*>( aField );
+ // Takes ownership of the field from the wrapper
+ CVPbkSimCntField* field = fieldWrapper->SimField();
+ CleanupStack::PushL( field );
+ // Add sim field to sim contact. Contact owns the field now.
+ iSimContact->AddFieldL( field );
+ CleanupStack::Pop( field );
+ // After this the function must not leave because client has created
+ // the fieldWrapper with CreateFieldLC and it's in the CleanupStack
+ // Client pops the fieldWrapper after this function
+ delete fieldWrapper;
+ // The field is appended to the array -> return the last field index.
+ return iSimContact->FieldCount() - 1;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::RemoveField
+// -----------------------------------------------------------------------------
+//
+void CContact::RemoveField( TInt aIndex )
+ {
+ __ASSERT_ALWAYS( aIndex >= 0 && aIndex < iFields.FieldCount(),
+ VPbkError::Panic(VPbkError::EInvalidFieldIndex) );
+ __ASSERT_ALWAYS( !iParentStore.StoreProperties().ReadOnly(),
+ VPbkError::Panic(VPbkError::EInvalidAccessToReadOnlyContact ) );
+
+ iSimContact->DeleteField( aIndex );
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::RemoveAllFields
+// -----------------------------------------------------------------------------
+//
+void CContact::RemoveAllFields()
+ {
+ __ASSERT_ALWAYS( !iParentStore.StoreProperties().ReadOnly(),
+ VPbkError::Panic(VPbkError::EInvalidAccessToReadOnlyContact ) );
+
+ iSimContact->DeleteAllFields();
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::LockL
+// -----------------------------------------------------------------------------
+//
+void CContact::LockL( MVPbkContactObserver& aObserver ) const
+ {
+ MVPbkContactObserver::TContactOpResult opResult;
+ opResult.iExtension = NULL;
+ opResult.iOpCode = MVPbkContactObserver::EContactLock;
+ opResult.iStoreContact = NULL;
+
+ CContactOperationCallback* callBack =
+ new( ELeave ) CContactOperationCallback( opResult, aObserver,
+ KErrNone );
+ CleanupStack::PushL( callBack );
+ iAsyncOp->CallbackL( callBack );
+ CleanupStack::Pop( callBack );
+ iLocked = ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::CommitL
+// -----------------------------------------------------------------------------
+//
+void CContact::CommitL( MVPbkContactObserver& aObserver ) const
+ {
+ if ( iLocked || iFlags.IsSet( KNewContact ))
+ {
+ if ( iStoreOperation )
+ {
+ User::Leave( KErrInUse );
+ }
+ // From the client point of view the MVPbkStoreContact is constant but
+ // implementation needs a non const contact.
+ iStoreOperation = iSimContact->SaveL( const_cast<CContact&>( *this ));
+ iObserver = &aObserver;
+ }
+ else
+ {
+ // Virtual Phonebook API demands that contact must be locked before
+ // CommitL. Sim Store has to behave according to that and
+ // complete with KErrAccessDenied.
+ MVPbkContactObserver::TContactOpResult opResult;
+ opResult.iExtension = NULL;
+ opResult.iOpCode = MVPbkContactObserver::EContactCommit;
+ opResult.iStoreContact = NULL;
+ CContactOperationCallback* callBack =
+ new( ELeave ) CContactOperationCallback(
+ opResult, aObserver, KErrAccessDenied );
+ CleanupStack::PushL( callBack );
+ iAsyncOp->CallbackL( callBack );
+ CleanupStack::Pop( callBack );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::GroupsJoinedLC
+// -----------------------------------------------------------------------------
+//
+MVPbkContactLinkArray* CContact::GroupsJoinedLC() const
+ {
+ return CVPbkContactLinkArray::NewLC();
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::Group
+// -----------------------------------------------------------------------------
+//
+MVPbkContactGroup* CContact::Group()
+ {
+ return NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::MaxNumberOfFieldL
+// -----------------------------------------------------------------------------
+//
+TInt CContact::MaxNumberOfFieldL( const MVPbkFieldType& aType ) const
+ {
+ TInt res = 0;
+ TVPbkSimCntFieldType nativeType =
+ iParentStore.FieldTypeMappings().Match( aType );
+ if ( nativeType != EVPbkSimUnknownType )
+ {
+ TVPbkUSimStoreProperty usimProp;
+ User::LeaveIfError(iParentStore.NativeStore().GetUSimStoreProperties(
+ usimProp ));
+ res = MaxNumberOfFieldsInContact( nativeType, usimProp );
+ }
+ return res;
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::ContactEventComplete
+// -----------------------------------------------------------------------------
+//
+void CContact::ContactEventComplete( TEvent aEvent,
+ CVPbkSimContact* /*aContact*/ )
+ {
+ __ASSERT_DEBUG( iObserver, Panic(EPreCond_CContact_ContactEventComplete));
+
+ delete iStoreOperation;
+ iStoreOperation = NULL;
+
+ MVPbkContactObserver::TContactOpResult vpbkOpResult;
+ vpbkOpResult.iStoreContact = NULL;
+ vpbkOpResult.iExtension = NULL;
+ vpbkOpResult.iOpCode = ConvertContactOperation( aEvent );
+
+ MVPbkContactObserver* observer = iObserver;
+ ResetContactOperationState();
+ observer->ContactOperationCompleted( vpbkOpResult );
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::ContactEventError
+// -----------------------------------------------------------------------------
+//
+void CContact::ContactEventError( TEvent aEvent,
+ CVPbkSimContact* /*aContact*/, TInt aError )
+ {
+ __ASSERT_DEBUG( iObserver, Panic(EPreCond_CContact_ContactEventError));
+
+ delete iStoreOperation;
+ iStoreOperation = NULL;
+
+ MVPbkContactObserver* observer = iObserver;
+ ResetContactOperationState();
+ MVPbkContactObserver::TContactOp op = ConvertContactOperation( aEvent );
+ observer->ContactOperationFailed( op, aError, EFalse );
+ }
+
+// -----------------------------------------------------------------------------
+// CContact::ResetContactOperationState
+// -----------------------------------------------------------------------------
+//
+void CContact::ResetContactOperationState()
+ {
+ iObserver = NULL;
+ }
+
+TAny* CContact::StoreContactExtension(TUid aExtensionUid)
+{
+
+ if( aExtensionUid == KMVPbkStoreContactExtension2Uid )
+ return static_cast<MVPbkStoreContact2*>( this );
+ return NULL;
+}
+
+
+
+MVPbkStoreContactProperties* CContact::PropertiesL() const
+ {
+ //sim store doesn't support any of MVPbkStoreContactProperties functions
+ return NULL;
+ }
+
+void CContact::SetAsOwnL( MVPbkContactObserver& /*aObserver*/ ) const
+ {
+ // own link is not supported in sim store
+ User::Leave( KErrNotSupported );
+ }
+
+} // namespace VPbkSimStore
+
+// end of file
+