/*
* 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: A class for combining data of two contacts
*
*/
// INCLUDE FILES
#include <CPbk2ContactMerge.h>
// From Phonebook2
#include "Pbk2PresentationUtils.h"
#include <MPbk2ContactNameFormatter.h>
#include <MPbk2FieldPropertyArray.h>
#include <MPbk2FieldProperty.h>
#include <RPbk2LocalizedResourceFile.h>
#include <Pbk2Presentation.rsg>
#include <Pbk2DataCaging.hrh>
// From Virtual Phonebook
#include <MVPbkFieldType.h>
#include <CVPbkContactManager.h>
#include <MVPbkStoreContactFieldCollection.h>
#include <MVPbkStoreContact.h>
#include <MVPbkContactFieldTextData.h>
#include <MVPbkContactFieldBinaryData.h>
#include <MVPbkContactFieldDateTimeData.h>
#include <CVPbkContactFieldIterator.h>
#include <MVPbkContactStore.h>
#include <MVPbkContactStoreProperties.h>
#include <TVPbkFieldVersitProperty.h>
#include <CVPbkFieldTypeSelector.h>
// From System
#include <barsread.h>
// ======== MEMBER FUNCTIONS ========
// ---------------------------------------------------------------------------
// CPbk2ContactMerge::CPbk2ContactMerge
// ---------------------------------------------------------------------------
//
CPbk2ContactMerge::CPbk2ContactMerge(
CVPbkContactManager& aContactManager,
MPbk2ContactNameFormatter& aNameFormatter,
const MPbk2FieldPropertyArray& aFieldProperties )
: iContactManager( aContactManager ),
iNameFormatter( aNameFormatter ),
iFieldProperties( aFieldProperties )
{
}
// ---------------------------------------------------------------------------
// CPbk2ContactMerge::~CPbk2ContactMerge
// ---------------------------------------------------------------------------
//
CPbk2ContactMerge::~CPbk2ContactMerge()
{
delete iEMailSelector;
delete iNumberSelector;
}
// ---------------------------------------------------------------------------
// CPbk2ContactMerge::NewL
// ---------------------------------------------------------------------------
//
EXPORT_C CPbk2ContactMerge* CPbk2ContactMerge::NewL(
CVPbkContactManager& aContactManager,
MPbk2ContactNameFormatter& aNameFormatter,
const MPbk2FieldPropertyArray& aFieldProperties )
{
CPbk2ContactMerge* self = new( ELeave ) CPbk2ContactMerge(
aContactManager, aNameFormatter, aFieldProperties );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
}
// ---------------------------------------------------------------------------
// CPbk2ContactMerge::ConstructL
// ---------------------------------------------------------------------------
//
void CPbk2ContactMerge::ConstructL()
{
RPbk2LocalizedResourceFile resFile( &iContactManager.FsSession() );
resFile.OpenLC( KPbk2RomFileDrive,
KDC_RESOURCE_FILES_DIR,
Pbk2PresentationUtils::PresentationResourceFile() );
TResourceReader reader;
reader.SetBuffer( resFile.AllocReadLC( R_PBK2_EMAIL_SELECTOR ) );
iEMailSelector = CVPbkFieldTypeSelector::NewL(
reader,
iContactManager.FieldTypes() );
CleanupStack::PopAndDestroy(); // reader
reader.SetBuffer( resFile.AllocReadLC( R_PBK2_NUMBER_SELECTOR ) );
iNumberSelector = CVPbkFieldTypeSelector::NewL(
reader,
iContactManager.FieldTypes() );
CleanupStack::PopAndDestroy(2); // reader, resFile
}
// ---------------------------------------------------------------------------
// CPbk2ContactMerge::MergeDataL
// ---------------------------------------------------------------------------
//
EXPORT_C TBool CPbk2ContactMerge::MergeDataL(
const MVPbkBaseContact& aContactFrom, MVPbkStoreContact& aContactTo )
{
TInt srcTitleFieldCount = 0;
TInt copiedFieldCount = 0;
const MVPbkBaseContactFieldCollection& srcFields = aContactFrom.Fields();
const TInt srcFieldCount = srcFields.FieldCount();
const MVPbkFieldTypeList& targetTypes =
aContactTo.ParentStore().StoreProperties().SupportedFields();
for ( TInt i = 0; i < srcFieldCount; ++i )
{
const MVPbkBaseContactField& srcField = srcFields.FieldAt( i );
const MVPbkFieldType* type = srcField.BestMatchingFieldType();
// Title fields are not merged
TBool titleField = iNameFormatter.IsTitleFieldType( *type );
if ( titleField )
{
++srcTitleFieldCount;
}
else if ( type && targetTypes.ContainsSame( *type ) )
{
CVPbkBaseContactFieldTypeIterator* iter =
CVPbkBaseContactFieldTypeIterator::NewLC( *type,
aContactTo.Fields() );
TInt maxNumOfFields = aContactTo.MaxNumberOfFieldL( *type );
TInt curFieldCount = 0;
while ( iter->HasNext() )
{
iter->Next();
++curFieldCount;
}
CleanupStack::PopAndDestroy( iter );
// Check field multiplicity
const MPbk2FieldProperty* prop =
iFieldProperties.FindProperty( *type );
if ( prop && prop->Multiplicity() == EPbk2FieldMultiplicityOne )
{
// If UI specification limits the number of certain type
// of field to one then check if the target contact
// already contains that type of field
if ( curFieldCount == 0 )
{
CopyFieldDataL( srcField, aContactTo );
++copiedFieldCount;
}
}
else if ( ( maxNumOfFields == KVPbkStoreContactUnlimitedNumber ||
curFieldCount < aContactTo.MaxNumberOfFieldL( *type )) &&
!FindMatch( srcField, aContactTo ))
{
// Field can be copied from source to destination. This is
// because target field count is not limited or target contact
// field limit is not exceeded.
CopyFieldDataL( srcField, aContactTo );
++copiedFieldCount;
}
}
}
// Return ETrue if all data fields from source contact were copied to target
return ( srcTitleFieldCount + copiedFieldCount ) == srcFieldCount;
}
// ---------------------------------------------------------------------------
// CPbk2ContactMerge::CopyFieldDataL
// ---------------------------------------------------------------------------
//
void CPbk2ContactMerge::CopyFieldDataL( const MVPbkBaseContactField& aField,
MVPbkStoreContact& aContactTo )
{
// Field has always a non NULL field type when this function is called
MVPbkStoreContactField* field = aContactTo.CreateFieldLC(
*aField.BestMatchingFieldType() );
field->FieldData().CopyL( aField.FieldData() );
aContactTo.AddFieldL( field );
CleanupStack::Pop(); // field
}
// ---------------------------------------------------------------------------
// CPbk2ContactMerge::FindMatch
// ---------------------------------------------------------------------------
//
TBool CPbk2ContactMerge::FindMatch( const MVPbkBaseContactField& aField,
MVPbkStoreContact& aContactTo )
{
TBool result = EFalse;
MVPbkStoreContactFieldCollection& fields = aContactTo.Fields();
const TInt count = fields.FieldCount();
// Check if any of the email fields contains a same email address
if ( iEMailSelector->IsFieldIncluded( aField ) )
{
for ( TInt i = 0 ; i < count && !result; ++i )
{
MVPbkStoreContactField& field = fields.FieldAt( i );
if ( iEMailSelector->IsFieldIncluded( field ) )
{
result = CompareData( aField.FieldData(),
field.FieldData() );
}
}
}
// Check if any of the number fields contains a same number
else if ( iNumberSelector->IsFieldIncluded( aField ) )
{
for ( TInt i = 0 ; i < count && !result; ++i )
{
MVPbkStoreContactField& field = fields.FieldAt( i );
if ( iNumberSelector->IsFieldIncluded( field ) )
{
result = CompareData( aField.FieldData(),
field.FieldData() );
}
}
}
// Check if there is a same type of field and if found, compare the data
else
{
const MVPbkFieldType* type = aField.BestMatchingFieldType();
if ( type )
{
// If iterator creation fails we cannot make comparison and
// the result is false.
TRAP_IGNORE(
{
CVPbkBaseContactFieldTypeIterator* iter =
CVPbkBaseContactFieldTypeIterator::NewLC( *type, fields );
while ( iter->HasNext() && !result )
{
const MVPbkBaseContactField* field = iter->Next();
result = CompareData( aField.FieldData(), field->FieldData() );
}
CleanupStack::PopAndDestroy( iter );
});
}
}
return result;
}
// ---------------------------------------------------------------------------
// CPbk2ContactMerge::CompareTextData
// ---------------------------------------------------------------------------
//
TBool CPbk2ContactMerge::CompareData( const MVPbkContactFieldData& aData1,
const MVPbkContactFieldData& aData2 )
{
TBool result = EFalse;
TVPbkFieldStorageType dataType = aData1.DataType();
if ( dataType == aData2.DataType() )
{
if ( dataType == EVPbkFieldStorageTypeText )
{
result = CompareTextData(
MVPbkContactFieldTextData::Cast( aData1 ),
MVPbkContactFieldTextData::Cast( aData2 ) );
}
else if ( dataType == EVPbkFieldStorageTypeBinary )
{
result = CompareBinaryData(
MVPbkContactFieldBinaryData::Cast( aData1 ),
MVPbkContactFieldBinaryData::Cast( aData2 ) );
}
else if ( dataType == EVPbkFieldStorageTypeDateTime )
{
result = CompareDateTimeData(
MVPbkContactFieldDateTimeData::Cast( aData1 ),
MVPbkContactFieldDateTimeData::Cast( aData2 ) );
}
}
return result;
}
// ---------------------------------------------------------------------------
// CPbk2ContactMerge::CompareTextData
// ---------------------------------------------------------------------------
//
TBool CPbk2ContactMerge::CompareTextData(
const MVPbkContactFieldTextData& aData1,
const MVPbkContactFieldTextData& aData2)
{
return aData1.Text().CompareF( aData2.Text() ) == 0;
}
// ---------------------------------------------------------------------------
// CPbk2ContactMerge::CompareBinaryData
// ---------------------------------------------------------------------------
//
TBool CPbk2ContactMerge::CompareBinaryData(
const MVPbkContactFieldBinaryData& aData1,
const MVPbkContactFieldBinaryData& aData2 )
{
return aData1.BinaryData().Compare( aData2.BinaryData() ) == 0;
}
// ---------------------------------------------------------------------------
// CPbk2ContactMerge::CompareDateTimeData
// ---------------------------------------------------------------------------
//
TBool CPbk2ContactMerge::CompareDateTimeData(
const MVPbkContactFieldDateTimeData& aData1,
const MVPbkContactFieldDateTimeData& aData2 )
{
return aData1.DateTime() == aData2.DateTime();
}