phonebookengines/VirtualPhonebook/VPbkSimStore/src/CContact.cpp
changeset 0 e686773b3f54
child 58 d4f567ce2e7c
--- /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
+