phonebookui/Phonebook2/Presentation/src/CPbk2ContactMerge.cpp
changeset 0 e686773b3f54
child 68 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/Presentation/src/CPbk2ContactMerge.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,327 @@
+/*
+* 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();
+    }