phonebookengines/VirtualPhonebook/VPbkVCardEng/src/CVPbkImportToStoreOperation.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/VirtualPhonebook/VPbkVCardEng/src/CVPbkImportToStoreOperation.cpp	Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,440 @@
+/*
+* Copyright (c) 2006-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:  An operation for importing and saving a contact to the store
+*
+*/
+
+
+#include "CVPbkImportToStoreOperation.h"
+
+#include "CVPbkVCardCompactBCardImporter.h"
+#include "CVPbkVCardImporter.h"
+#include "CVPbkVCardData.h"
+#include "VPbkVCardEngError.h"
+#include "CVPbkLocalVariationManager.h"
+
+// From Virtual Phonebook
+#include <MVPbkStoreContact.h>
+#include <MVPbkContactStore.h>
+#include <MVPbkContactStoreProperties.h>
+#include <MVPbkContactStoreProperties2.h>
+#include <CVPbkContactLinkArray.h>
+#include <MVPbkContactCopyPolicy.h>
+#include <MVPbkContactLink.h>
+#include <MVPbkContactDuplicatePolicy.h>
+
+/// Unnamed namespace for local definitions
+namespace 
+    {
+    // Max number of duplicate contacts to find
+    const TInt KDuplicatesToFind = 1;
+    }
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CVPbkImportToStoreOperation::CVPbkImportToStoreOperation
+// ---------------------------------------------------------------------------
+//
+CVPbkImportToStoreOperation::CVPbkImportToStoreOperation(
+        MVPbkContactCopyObserver& aObserver,
+        MVPbkContactStore& aTargetStore )
+        :   iTargetStore( aTargetStore ),
+            iObserver( aObserver )
+    {
+    iOwncardHandler = NULL;
+    iGroupcardHandler = NULL;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CVPbkImportToStoreOperation::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::ConstructL( TVPbkImportCardType aType,
+        RReadStream &aSourceStream, CVPbkVCardData& aData, TBool aSync )
+    {
+    iCopyPolicy = &aData.CopyPolicyL( iTargetStore.StoreProperties().Uri() );
+    if ( !iCopyPolicy )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    // If contact data merge is supported then use duplicate checking
+    // before copying.
+    // During sync duplicate policy is ignored to improve performance
+    if ( iCopyPolicy->SupportsContactMerge() && ! aSync )
+        {
+           iDuplicatePolicy = aData.DuplicatePolicy();
+        }
+
+    if ( aType == ECompactBusinessCard )
+        {
+        iOperationImpl = CVPbkVCardCompactBCardImporter::NewL(
+            iImportedContacts, iTargetStore, aSourceStream, aData );
+        }
+    else if ( aType == EVCard )
+        {
+        iOperationImpl = CVPbkVCardImporter::NewL(
+            iImportedContacts, aSourceStream, iTargetStore, aData );
+        }
+    else
+        {
+        User::Leave( KErrArgument );
+        }
+
+    iSavedContacts = CVPbkContactLinkArray::NewL();
+    
+   // Handle Owncard during Sync
+    if(aSync)
+	    {
+        MVPbkContactStoreProperties& prop = 
+                const_cast<MVPbkContactStoreProperties&>(
+                        iTargetStore.StoreProperties());
+        if ( prop.SupportsContactGroups() )
+            {
+            iGroupcardHandler = CVPbkGroupCardHandler::NewL(aData);
+            }
+        MVPbkContactStoreProperties2* prop2 = 
+                    static_cast<MVPbkContactStoreProperties2*>( 
+                            prop.ContactStorePropertiesExtension( 
+                                    KMVPbkContactStorePropertiesExtension2Uid ) );
+        if ( prop2 && prop2->SupportsOwnContact() )
+            {
+            iOwncardHandler = CVPbkOwnCardHandler::NewL(aData);
+            }
+	    }
+    }
+
+// ---------------------------------------------------------------------------
+// CVPbkImportToStoreOperation::NewL
+// ---------------------------------------------------------------------------
+//
+CVPbkImportToStoreOperation* CVPbkImportToStoreOperation::NewL(
+        TVPbkImportCardType aType,
+        MVPbkContactStore& aTargetStore,
+        RReadStream& aSourceStream,
+        CVPbkVCardData& aData,
+        MVPbkContactCopyObserver& aObserver,
+        TBool aSync )
+    {
+    CVPbkImportToStoreOperation* self =
+        new( ELeave ) CVPbkImportToStoreOperation( aObserver, aTargetStore );
+    CleanupStack::PushL( self );
+    self->ConstructL( aType, aSourceStream, aData, aSync );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CVPbkImportToStoreOperation::~CVPbkImportToStoreOperation
+// ---------------------------------------------------------------------------
+//
+CVPbkImportToStoreOperation::~CVPbkImportToStoreOperation()
+    {
+    delete iVPbkOperation;
+    delete iSavedContacts;
+    delete iOperationImpl;
+    iImportedContacts.ResetAndDestroy();
+    iDuplicates.ResetAndDestroy();
+    delete iOwncardHandler;
+    delete iGroupcardHandler;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MVPbkContactOperation
+// CVPbkImportToStoreOperation::StartL
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::StartL()
+    {
+    __ASSERT_DEBUG( iOperationImpl, VPbkVCardEngError::Panic(
+        VPbkVCardEngError::EPreCond_CVPbkImportToStoreOperation_StartL ) );
+
+    iOperationImpl->SetObserver( *this );
+    iOperationImpl->StartL();
+    }
+
+// ---------------------------------------------------------------------------
+// From class MVPbkContactOperation
+// CVPbkImportToStoreOperation::Cancel
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::Cancel()
+    {
+    delete iOperationImpl;
+    iOperationImpl = NULL;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MVPbkImportOperationObserver
+// CVPbkImportToStoreOperation::ContactsImported
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::ContactsImported()
+    {
+    TInt err( KErrNone );
+    if ( iImportedContacts.Count() == 0 )
+        {
+        err = KErrNotFound;
+        }
+    else if ( iDuplicatePolicy )
+        {
+        ResetOperation();
+        iDuplicates.ResetAndDestroy();
+        TRAP( err, iVPbkOperation = iDuplicatePolicy->FindDuplicatesL(
+            *iImportedContacts[0], iTargetStore, iDuplicates, *this,
+            KDuplicatesToFind ) );
+        }
+    else
+        {
+        TRAP( err, CommitNextContactL() );
+        }
+    // delegate errors
+    if ( err != KErrNone )
+        {
+        ContactImportingFailed( err );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From class MVPbkImportOperationObserver
+// CVPbkImportToStoreOperation::ContactsImportedCompleted
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::ContactsImportingCompleted()
+{
+    MVPbkContactLinkArray* results = iSavedContacts;
+    iSavedContacts = NULL;
+    
+    // Notice that client can delete this operation in
+    // ContactsSaved so there must be no usage of member data
+    // after calling this.
+    if (results->Count())
+        {
+        // One or more successfully saved contacts
+        iObserver.ContactsSaved( *this, results );
+        }
+    else
+        {
+        // No imported and saved contacts available
+        ContactImportingFailed(KErrNotFound);
+        }
+    
+};
+
+// ---------------------------------------------------------------------------
+// From class MVPbkImportOperationObserver
+// CVPbkImportToStoreOperation::ContactImportingFailed
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::ContactImportingFailed( TInt aError )
+    {
+    iObserver.ContactsSavingFailed( *this, aError );
+    }
+
+// ---------------------------------------------------------------------------
+// From class MVPbkImportOperationObserver
+// CVPbkImportToStoreOperation::ContactsSaved
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::ContactsSaved(
+        MVPbkContactOperationBase& /*aOperation*/,
+        MVPbkContactLinkArray* aResults )
+    {
+    ResetOperation();
+    TRAPD( res, HandleContactSavedL( aResults ) );
+    if ( res != KErrNone )
+        {
+        ContactImportingFailed( res );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From class MVPbkImportOperationObserver
+// CVPbkImportToStoreOperation::ContactsSavingFailed
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::ContactsSavingFailed(
+        MVPbkContactOperationBase& /*aOperation*/,
+        TInt aError)
+    {
+    ContactImportingFailed( aError );
+    }
+
+// ---------------------------------------------------------------------------
+// From class MVPbkContactFindObserver
+// CVPbkImportToStoreOperation::FindCompleteL
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::FindCompleteL(
+        MVPbkContactLinkArray* aResults )
+    {
+    // Links not needed
+    delete aResults;
+
+    if ( iDuplicates.Count() > 0 )
+        {
+        // Merge and commit, let policy decide how to handle merge and
+        // what to do with imported contacts. Policy takes the contacts.
+        ResetOperation();
+        iVPbkOperation = iCopyPolicy->MergeAndSaveContactsL(
+            iImportedContacts, *iDuplicates[0], *this );
+        }
+    else
+        {
+        // No duplicates, save imported contacts.
+        CommitNextContactL();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From class MVPbkContactFindObserver
+// CVPbkImportToStoreOperation::FindFailed
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::FindFailed( TInt aError )
+    {
+    ContactImportingFailed( aError );
+    }
+
+// ---------------------------------------------------------------------------
+// CVPbkImportToStoreOperation::CommitNextContactL
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::CommitNextContactL()
+    {
+    __ASSERT_DEBUG( iImportedContacts.Count() > 0,
+        VPbkVCardEngError::Panic(
+            VPbkVCardEngError::EPreCond_CommitNextContactL ) );
+    const TInt firstContact = 0;
+    MVPbkStoreContact* contact = iImportedContacts[firstContact];
+    /// contact ownership is given
+    ResetOperation();
+    iVPbkOperation = iCopyPolicy->CommitContactL( contact, *this );
+    iImportedContacts.Remove( firstContact );
+    }
+
+// ---------------------------------------------------------------------------
+// CVPbkImportToStoreOperation::HandleContactSavedL
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::HandleContactSavedL(
+        MVPbkContactLinkArray* aResults )
+    {
+    CleanupDeletePushL( aResults );
+    const TInt count = aResults->Count();
+    
+    TBool added = EFalse;
+    for ( TInt i = 0; i < count; ++i )
+        {
+        iSavedContacts->AppendL( (*aResults)[i].CloneLC() );
+        added = ETrue;
+        CleanupStack::Pop();
+        }
+
+    const TInt duplicateCount = iDuplicates.Count();
+    const TInt curUnsavedCount = iImportedContacts.Count();
+    // Duplicates are returned to the client if following conditions apply
+    // 1) There are duplicates (iDuplicates.Count() > 0)
+    // 2) All imported contacts have been saved (iImportedContacts.Count() == 0)
+    // 3) Copy policy didn't actually save anything
+    //    (iSavedContacts->Count() == 0 )
+    //if ( ( duplicateCount > 0 ) &&
+    //     ( curUnsavedCount == 0 ) &&
+    //     ( iSavedContacts->Count() == 0 ) )
+         
+     if ( ( duplicateCount > 0 ) &&
+          ( curUnsavedCount == 0 ) &&
+          ( added == EFalse ) )     
+        {
+        for ( TInt k = 0; k < duplicateCount; ++k )
+            {
+            iSavedContacts->AppendL( iDuplicates[k]->CreateLinkLC() );
+            CleanupStack::Pop();
+            }
+        }
+		if(iOwncardHandler && iOperationImpl->IsOwncard())
+	        {
+	    	iOwncardHandler->SetAsOwnContactL(aResults->At(0));
+	    	}
+		
+     TBool destroyed = EFalse;
+     TBool isGroupCard = ((CVPbkVCardImporter *)iOperationImpl)->IsGroupcard();   
+     if(iGroupcardHandler && isGroupCard )
+         {
+         // CVPbkGroupCardHandler uses nested activescheduler loop to make
+         // async requests synchronous (why?). Hence it is possible that when 
+         // the execution returns from BuildContactGroupsHashMapL, 
+         // GetContactGroupStoreL or DecodeContactGroupInVCardL this instance
+         // has already been deleted and member data can not be accessed
+         // anymore. User can e.g cancel restoring contacts in which case
+         // import operation will be deleted before it is completed.
+         // Self pointer is used to check this.
+         CVPbkGroupCardHandler* groupcardHandler = iGroupcardHandler;  
+         groupcardHandler->BuildContactGroupsHashMapL(iTargetStore, &groupcardHandler);
+         if ( groupcardHandler )
+             {
+             groupcardHandler->GetContactGroupStoreL(aResults->At(0), &groupcardHandler );
+             }
+         if ( groupcardHandler )
+             {
+             groupcardHandler->DecodeContactGroupInVCardL(
+                     ((CVPbkVCardImporter *)iOperationImpl)->GetGroupcardvalue(), 
+                     &groupcardHandler);
+             }
+         else
+             {
+             destroyed = ETrue;
+             }
+         }
+     
+     CVPbkLocalVariationManager* lvm = CVPbkLocalVariationManager::NewL(); 
+     TBool supportSyncGroupVcard = lvm->LocallyVariatedFeatureEnabled( EVPbkLVSyncGroupEnabled );
+     delete lvm;    
+     if (supportSyncGroupVcard && iGroupcardHandler && !isGroupCard)        
+         {
+         iGroupcardHandler->BuildContactGroupsHashMapL(iTargetStore);
+         iGroupcardHandler->GetContactGroupStoreL(aResults->At(0));
+         iGroupcardHandler->DeleteContactFromGroupsL();
+         }
+     
+    CleanupStack::PopAndDestroy(); // aResults
+
+    if ( !destroyed )
+        {
+        if ( curUnsavedCount == 0 )
+            {
+            // Try to read the next entry, if one existed
+            iOperationImpl->StartL();
+            }
+        else
+            {
+            CommitNextContactL();
+            iOperationImpl->StartL();
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CVPbkImportToStoreOperation::ResetOperation
+// ---------------------------------------------------------------------------
+//
+void CVPbkImportToStoreOperation::ResetOperation()
+    {
+    delete iVPbkOperation;
+    iVPbkOperation = NULL;
+    }
+// End of file