phonebookengines/VirtualPhonebook/VPbkVCardEng/src/CVPbkImportToStoreOperation.cpp
/*
* 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