phonebookengines/VirtualPhonebook/VPbkEng/src/CVPbkCopyContactsOperation.cpp
changeset 0 e686773b3f54
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 /*
       
     2 * Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Copy contacts operation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "CVPbkCopyContactsOperation.h"
       
    20 
       
    21 #include <MVPbkBatchOperationObserver.h>
       
    22 #include <MVPbkStoreContactFieldCollection.h>
       
    23 #include <MVPbkStoreContactField.h>
       
    24 #include <MVPbkStoreContact.h>
       
    25 #include <MVPbkContactStore.h>
       
    26 #include <MVPbkContactFieldData.h>
       
    27 #include <MVPbkFieldType.h>
       
    28 #include <CVPbkContactManager.h>
       
    29 #include <MVPbkContactStoreProperties.h>
       
    30 #include <MVPbkContactLinkArray.h>
       
    31 #include <MVPbkContactLink.h>
       
    32 #include <CVPbkContactCopyPolicyManager.h>
       
    33 #include <MVPbkContactCopyPolicy.h>
       
    34 #include <MVPbkContactOperationBase.h>
       
    35 #include <CVPbkContactCopier.h>
       
    36 #include <CVPbkContactDuplicatePolicy.h>
       
    37 
       
    38 namespace {
       
    39 
       
    40 const TInt KOneStep = 1;
       
    41 const TInt KDuplicatesToFind = 1;
       
    42 
       
    43 TInt CurNumberOfField( MVPbkStoreContact& aContact,
       
    44         const MVPbkFieldType& aFieldType )
       
    45     {
       
    46     MVPbkStoreContactFieldCollection& fields = aContact.Fields();
       
    47     TInt res = 0;
       
    48     const TInt count = fields.FieldCount();
       
    49     for (TInt i = 0; i < count; ++i)
       
    50         {
       
    51         const MVPbkFieldType* type = fields.FieldAt(i).BestMatchingFieldType();
       
    52         if (type && type->IsSame(aFieldType))
       
    53             {
       
    54             ++res;
       
    55             }
       
    56         }
       
    57     return res;
       
    58     }
       
    59 }
       
    60 
       
    61 CVPbkCopyContactsOperation::CVPbkCopyContactsOperation(
       
    62         CVPbkContactManager& aContactManager,
       
    63         const MVPbkContactLinkArray& aLinks,
       
    64         MVPbkContactStore* aTargetStore,
       
    65         CVPbkContactLinkArray* aCopiedContactLinks,
       
    66         MVPbkBatchOperationObserver& aObserver)
       
    67         :   CActive( EPriorityStandard ),
       
    68             iContactManager( aContactManager ),
       
    69             iLinks( aLinks ),
       
    70             iTargetStore( aTargetStore ),
       
    71             iCopiedContactLinks( aCopiedContactLinks ),
       
    72             iObserver( aObserver ),
       
    73             iState( ERetrieveNextContact )
       
    74     {
       
    75     CActiveScheduler::Add(this);
       
    76     }
       
    77 
       
    78 inline void CVPbkCopyContactsOperation::ConstructL( TUint32 aCopyContactFlags )
       
    79     {
       
    80     // If client gave NULL target store then contacts are duplicated
       
    81     if ( !iTargetStore )
       
    82         {
       
    83         iDuplicateContacts = ETrue;
       
    84         }
       
    85 
       
    86     SetTargetStoreL();
       
    87 
       
    88     const TUint32 copyPolicyFlags =
       
    89         CVPbkContactCopier::EVPbkUseStoreSpecificCopyPolicy |
       
    90         CVPbkContactCopier::EVPbkUsePlatformSpecificDuplicatePolicy;
       
    91     const TUint32 duplicatePolicyFlags =
       
    92         CVPbkContactCopier::EVPbkUsePlatformSpecificDuplicatePolicy;
       
    93 
       
    94     // Check if copy policy is needed
       
    95     if ( aCopyContactFlags & copyPolicyFlags )
       
    96         {
       
    97         iCopyPolicyManager = CVPbkContactCopyPolicyManager::NewL();
       
    98         if ( iTargetStore )
       
    99             {
       
   100             iCopyPolicy = iCopyPolicyManager->GetPolicyL( iContactManager,
       
   101                 iTargetStore->StoreProperties().Uri() );
       
   102             }
       
   103         }
       
   104 
       
   105     // Check if duplicate policy is needed
       
   106     if ( aCopyContactFlags & duplicatePolicyFlags && iCopyPolicy &&
       
   107          iCopyPolicy->SupportsContactMerge() )
       
   108         {
       
   109         CVPbkContactDuplicatePolicy::TParam param( iContactManager );
       
   110         TRAPD( res, iDuplicatePolicy = CVPbkContactDuplicatePolicy::NewL( param ));
       
   111         // Don't leave if duplicate policy is not found -> duplicate checking
       
   112         // is not used.
       
   113         if ( res != KErrNone && res != KErrNotFound )
       
   114             {
       
   115             User::LeaveIfError( res );
       
   116             }
       
   117         }
       
   118     }
       
   119 
       
   120 CVPbkCopyContactsOperation* CVPbkCopyContactsOperation::NewLC(
       
   121         TUint32 aCopyContactFlags,
       
   122         CVPbkContactManager& aContactManager,
       
   123         const MVPbkContactLinkArray& aLinks,
       
   124         MVPbkContactStore* aTargetStore,
       
   125         CVPbkContactLinkArray* aCopiedContactLinks,
       
   126         MVPbkBatchOperationObserver& aObserver)
       
   127     {
       
   128     CVPbkCopyContactsOperation* self = new(ELeave) CVPbkCopyContactsOperation(
       
   129             aContactManager,
       
   130             aLinks,
       
   131             aTargetStore,
       
   132             aCopiedContactLinks,
       
   133             aObserver);
       
   134     CleanupStack::PushL(self);
       
   135     self->ConstructL( aCopyContactFlags );
       
   136     return self;
       
   137     }
       
   138 
       
   139 CVPbkCopyContactsOperation::~CVPbkCopyContactsOperation()
       
   140     {
       
   141     Cancel();
       
   142     delete iDuplicatePolicy;
       
   143     delete iCopyPolicyManager;
       
   144     delete iStoreContact;
       
   145     delete iOperation;
       
   146     iDuplicates.ResetAndDestroy();
       
   147     iSourceContactsForMerge.ResetAndDestroy();
       
   148     }
       
   149 
       
   150 void CVPbkCopyContactsOperation::DoCancel()
       
   151     {
       
   152     }
       
   153 
       
   154 void CVPbkCopyContactsOperation::RunL()
       
   155     {
       
   156     switch (iState)
       
   157         {
       
   158         case ERetrieveNextContact:
       
   159             {
       
   160             RetrieveNextContactL();
       
   161             break;
       
   162             }
       
   163         case EDefaultCopy:
       
   164             {
       
   165             DefaultCopyL();
       
   166             break;
       
   167             }
       
   168         case ECopyUsingPolicy:
       
   169             {
       
   170             CopyUsingPolicyL();
       
   171             break;
       
   172             }
       
   173         case EFindDuplicates:
       
   174             {
       
   175             FindDuplicatesL();
       
   176             break;
       
   177             }
       
   178         case EComplete:
       
   179             {
       
   180             iObserver.OperationComplete(*this);
       
   181             break;
       
   182             }
       
   183         }
       
   184     }
       
   185 
       
   186 TInt CVPbkCopyContactsOperation::RunError(TInt aError)
       
   187     {
       
   188     ContinueAfterFailure( aError );
       
   189     return KErrNone;
       
   190     }
       
   191 
       
   192 void CVPbkCopyContactsOperation::StartL()
       
   193     {
       
   194     IssueRequest();
       
   195     }
       
   196 
       
   197 void CVPbkCopyContactsOperation::Cancel()
       
   198     {
       
   199     CActive::Cancel();
       
   200     }
       
   201 
       
   202 void CVPbkCopyContactsOperation::VPbkSingleContactOperationComplete(
       
   203         MVPbkContactOperationBase& /*aOperation*/,
       
   204         MVPbkStoreContact* aContact)
       
   205     {
       
   206     delete iOperation;
       
   207     iOperation = NULL;
       
   208     delete iStoreContact;
       
   209     iStoreContact = aContact;
       
   210 
       
   211     // Default action is own copy logic
       
   212     iState = EDefaultCopy;
       
   213     if ( iDuplicatePolicy && iCopyPolicy )
       
   214         {
       
   215         // But if the duplicate policy exists it's done before copying
       
   216         iState = EFindDuplicates;
       
   217         }
       
   218     else if ( iCopyPolicy )
       
   219         {
       
   220         // Duplicate checking was not defined but copy policy was.
       
   221         // Make more advanced copy using the policy
       
   222         iState = ECopyUsingPolicy;
       
   223         }
       
   224     IssueRequest();
       
   225     }
       
   226 
       
   227 void CVPbkCopyContactsOperation::VPbkSingleContactOperationFailed(
       
   228         MVPbkContactOperationBase& /*aOperation*/,
       
   229         TInt aError)
       
   230     {
       
   231     delete iOperation;
       
   232     iOperation = NULL;
       
   233 
       
   234     ContinueAfterFailure( aError );
       
   235     }
       
   236 
       
   237 void CVPbkCopyContactsOperation::ContactsSaved(
       
   238         MVPbkContactOperationBase& aOperation,
       
   239         MVPbkContactLinkArray* aResults)
       
   240     {
       
   241     delete iOperation;
       
   242     iOperation = NULL;
       
   243     delete iStoreContact;
       
   244     iStoreContact = NULL;
       
   245 
       
   246     TRAPD( res,
       
   247         {
       
   248         CleanupDeletePushL( aResults );
       
   249         AppendResultsL( *aResults );
       
   250         CleanupStack::PopAndDestroy(); // aResults
       
   251         });
       
   252 
       
   253     if ( res == KErrNone )
       
   254         {
       
   255         // One contact copied, notify observer and start retrieve next contact.
       
   256         iObserver.StepComplete( *this, KOneStep );
       
   257 
       
   258         iState = ERetrieveNextContact;
       
   259         IssueRequest();
       
   260         }
       
   261     else
       
   262         {
       
   263         ContactsSavingFailed( aOperation, res );
       
   264         }
       
   265     }
       
   266 
       
   267 void CVPbkCopyContactsOperation::ContactsSavingFailed(
       
   268         MVPbkContactOperationBase& /*aOperation*/,
       
   269         TInt aError)
       
   270     {
       
   271     ContinueAfterFailure( aError );
       
   272     }
       
   273 
       
   274 void CVPbkCopyContactsOperation::ContactOperationCompleted(
       
   275         TContactOpResult aResult )
       
   276     {
       
   277     // Default copy successfully done -> continue with next contact
       
   278     delete iOperation;
       
   279     iOperation = NULL;
       
   280 
       
   281     TRAPD( res,
       
   282         {
       
   283         if ( iCopiedContactLinks )
       
   284             {
       
   285             iCopiedContactLinks->AppendL( iStoreContact->CreateLinkLC() );
       
   286             CleanupStack::Pop(); // link
       
   287             }
       
   288         });
       
   289 
       
   290     if ( res == KErrNone )
       
   291         {
       
   292         iObserver.StepComplete( *this, KOneStep );
       
   293         iState = ERetrieveNextContact;
       
   294         IssueRequest();
       
   295         }
       
   296     else
       
   297         {
       
   298         ContactOperationFailed( aResult.iOpCode, res, EFalse );
       
   299         }
       
   300     }
       
   301 
       
   302 void CVPbkCopyContactsOperation::ContactOperationFailed( TContactOp /*aOpCode*/,
       
   303         TInt aErrorCode, TBool /*aErrorNotified*/ )
       
   304     {
       
   305     // Default copy failed -> send step failed and continue with next contact
       
   306     ContinueAfterFailure( aErrorCode );
       
   307     }
       
   308 
       
   309 void CVPbkCopyContactsOperation::FindCompleteL( MVPbkContactLinkArray* aResults )
       
   310     {
       
   311     delete aResults;
       
   312     delete iOperation;
       
   313     iOperation = NULL;
       
   314 
       
   315     if ( iDuplicates.Count() > 0 )
       
   316         {
       
   317         // Merge iStoreContact to the duplicate.
       
   318         iSourceContactsForMerge.ResetAndDestroy();
       
   319         /// Ownership of the iStoreContact changes
       
   320         iSourceContactsForMerge.AppendL( iStoreContact );
       
   321         iStoreContact = NULL;
       
   322         iOperation = iCopyPolicy->MergeAndSaveContactsL(
       
   323             iSourceContactsForMerge, *iDuplicates[0], *this );
       
   324         }
       
   325     else
       
   326         {
       
   327         // No duplicates found -> use copy policy to copy contact
       
   328         iState = ECopyUsingPolicy;
       
   329         IssueRequest();
       
   330         }
       
   331     }
       
   332 
       
   333 void CVPbkCopyContactsOperation::FindFailed( TInt aError )
       
   334     {
       
   335     ContinueAfterFailure( aError );
       
   336     }
       
   337 
       
   338 void CVPbkCopyContactsOperation::IssueRequest()
       
   339     {
       
   340     TRequestStatus* status = &iStatus;
       
   341     User::RequestComplete(status, KErrNone);
       
   342     SetActive();
       
   343     }
       
   344 
       
   345 void CVPbkCopyContactsOperation::SetTargetStoreL()
       
   346     {
       
   347     if ( iDuplicateContacts && iCurrentLinkIndex < iLinks.Count() )
       
   348         {
       
   349         // if duplicates are created then set the store to the store of the
       
   350         // current link
       
   351         iTargetStore = &iLinks.At( iCurrentLinkIndex ).ContactStore();
       
   352         if ( iTargetStore && iCopyPolicyManager )
       
   353             {
       
   354             iCopyPolicy = iCopyPolicyManager->GetPolicyL( iContactManager,
       
   355                     iTargetStore->StoreProperties().Uri() );
       
   356             }
       
   357         }
       
   358     }
       
   359 
       
   360 void CVPbkCopyContactsOperation::RetrieveNextContactL()
       
   361     {
       
   362     // In duplicate mode target store is same as source store
       
   363     // so this needs to be checked every time
       
   364     SetTargetStoreL();
       
   365 
       
   366     delete iStoreContact;
       
   367     iStoreContact = NULL;
       
   368 
       
   369     if ( iCurrentLinkIndex < iLinks.Count() )
       
   370         {
       
   371         iOperation = iContactManager.RetrieveContactL(
       
   372                 iLinks.At( iCurrentLinkIndex++ ), *this);
       
   373         }
       
   374     else
       
   375         {
       
   376         iState = EComplete;
       
   377         IssueRequest();
       
   378         }
       
   379     }
       
   380 
       
   381 void CVPbkCopyContactsOperation::DefaultCopyL()
       
   382     {
       
   383     // Own simple copy logic. Copy the field if the target supports it and
       
   384     // store contact has space for the new field.
       
   385     // Copy labels if target field supports label.
       
   386     const MVPbkContactStoreProperties& props = iTargetStore->StoreProperties();
       
   387     const MVPbkFieldTypeList& supportedFields = props.SupportedFields();
       
   388     MVPbkStoreContact* newContact = iTargetStore->CreateNewContactLC();
       
   389     MVPbkStoreContactFieldCollection& fields = iStoreContact->Fields();
       
   390     const TInt fieldCount = fields.FieldCount();
       
   391     for (TInt i = 0; i < fieldCount; ++i)
       
   392         {
       
   393         MVPbkStoreContactField& field = fields.FieldAt(i);
       
   394         const MVPbkFieldType* fieldType = field.BestMatchingFieldType();
       
   395         if (fieldType && supportedFields.ContainsSame(*fieldType))
       
   396             {
       
   397             TInt maxNumber = newContact->MaxNumberOfFieldL(*fieldType);
       
   398             if (maxNumber == KVPbkStoreContactUnlimitedNumber ||
       
   399                 CurNumberOfField(*newContact, *fieldType) < maxNumber)
       
   400                 {
       
   401                 MVPbkStoreContactField* newField =
       
   402                     newContact->CreateFieldLC(*fieldType);
       
   403                 TPtrC label(field.FieldLabel());
       
   404                 if (newField->SupportsLabel() &&
       
   405                     label.Length() > 0)
       
   406                     {
       
   407                     newField->SetFieldLabelL(label);
       
   408                     }
       
   409                 newField->FieldData().CopyL(field.FieldData());
       
   410                 newContact->AddFieldL(newField);
       
   411                 CleanupStack::Pop(); // newField
       
   412                 }
       
   413             }
       
   414         }
       
   415 
       
   416     if ( newContact->Fields().FieldCount() > 0 )
       
   417         {
       
   418         // Save the new contact if fields were copied
       
   419         delete iStoreContact;
       
   420         iStoreContact = newContact;
       
   421         CleanupStack::Pop(); // newContact
       
   422         iStoreContact->CommitL( *this );
       
   423         }
       
   424     else
       
   425         {
       
   426         // No fields were copied -> Continue with next contact.
       
   427         CleanupStack::PopAndDestroy(); // newContact
       
   428         // Return success.
       
   429         iObserver.StepComplete( *this, KOneStep );
       
   430         iState = ERetrieveNextContact;
       
   431         IssueRequest();
       
   432         }
       
   433     }
       
   434 
       
   435 void CVPbkCopyContactsOperation::CopyUsingPolicyL()
       
   436     {
       
   437     iOperation = iCopyPolicy->CopyContactL( *iStoreContact, *iTargetStore,
       
   438         *this );
       
   439     }
       
   440 
       
   441 void CVPbkCopyContactsOperation::FindDuplicatesL()
       
   442     {
       
   443     iDuplicates.ResetAndDestroy();
       
   444     iOperation = iDuplicatePolicy->FindDuplicatesL( *iStoreContact,
       
   445         *iTargetStore, iDuplicates, *this, KDuplicatesToFind );
       
   446     }
       
   447 
       
   448 void CVPbkCopyContactsOperation::ContinueAfterFailure( TInt aError )
       
   449     {
       
   450     delete iOperation;
       
   451     iOperation = NULL;
       
   452 
       
   453     iState = EComplete;
       
   454     if ( iObserver.StepFailed( *this, KOneStep, aError ) )
       
   455         {
       
   456         // Continue only if ETrue is answered. This operation might be deleted
       
   457         // if EFalse is answered.
       
   458         iState = ERetrieveNextContact;
       
   459         IssueRequest();
       
   460         }
       
   461     }
       
   462 
       
   463 void CVPbkCopyContactsOperation::AppendResultsL( MVPbkContactLinkArray& aLinks )
       
   464     {
       
   465     if ( iCopiedContactLinks )
       
   466         {
       
   467         const TInt count = aLinks.Count();
       
   468         for ( TInt i = 0; i < count; ++i )
       
   469             {
       
   470             iCopiedContactLinks->AppendL( aLinks.At(i).CloneLC() );
       
   471             CleanupStack::Pop(); // link
       
   472             }
       
   473         }
       
   474     }
       
   475 // End of File