phonebookengines/VirtualPhonebook/VPbkEng/src/CVPbkPhoneNumberMatchStrategy.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
child 68 9da50d567e3c
equal deleted inserted replaced
62:5b6f26637ad3 63:f4a778e096c2
       
     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:  A high level class for matching phone numbers from stores.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDES
       
    20 #include <CVPbkPhoneNumberMatchStrategy.h>
       
    21 
       
    22 #include <CVPbkContactManager.h>
       
    23 #include <CVPbkContactLinkArray.h>
       
    24 #include <MVPbkContactOperation.h>
       
    25 #include <MVPbkContactStoreList.h>
       
    26 #include <MVPbkContactStore.h>
       
    27 #include <MVPbkContactStoreProperties.h>
       
    28 #include <MVPbkContactLink.h>
       
    29 #include <MVPbkStoreContact.h>
       
    30 #include <MVPbkSingleContactOperationObserver.h>
       
    31 #include <RLocalizedResourceFile.h>
       
    32 #include <VPbkDataCaging.hrh>
       
    33 #include <VPbkEng.rsg>
       
    34 #include <VPbkFieldTypeSelectors.rsg>
       
    35 #include <CVPbkFieldTypeSelector.h>
       
    36 #include <CVPbkFieldFilter.h>
       
    37 #include <barsread.h>
       
    38 #include <MVPbkContactFieldTextData.h>
       
    39 #include <CVPbkContactStoreUriArray.h>
       
    40 #include <centralrepository.h>
       
    41 #include <VPbkStoreUriLiterals.h>
       
    42 
       
    43 #include "CVPbkPhoneNumberSequentialMatchStrategy.h"
       
    44 #include "CVPbkPhoneNumberParallelMatchStrategy.h"
       
    45 #include "CVPbkETelCntConverter.h"
       
    46 
       
    47 #include <cntdb.h>
       
    48 #include <ecom/ecom.h>
       
    49 
       
    50 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    51 #include <cntphonenumparser.h>
       
    52 #endif
       
    53 // CONSTANTS
       
    54 // Unnamed namespace for local definitions
       
    55 namespace {
       
    56 // --------------------------------------------------------------------------
       
    57 // Phonebook Central Repository UIDs
       
    58 // Copied from sf\app\contacts\phonebookui\Phonebook2\inc\Phonebook2InternalCRKeys.h
       
    59 // --------------------------------------------------------------------------
       
    60 //
       
    61 const TUint32 KCRUidPhonebookStoreConfiguration             = 0x1020727f;
       
    62 const TUint32 KPhonebookCurrentConfigurationPartialKey      = 0x00000100;
       
    63 const TUint32 KPhonebookCurrentConfigurationMask            = 0xffffff00;
       
    64 
       
    65 const TInt KInitialStoreUriSize = 22; // length of KVPbkDefaultCntDbURI
       
    66 const TInt KMagicNumber = -1;
       
    67 } // namespace
       
    68 
       
    69 NONSHARABLE_CLASS(CVPbkPhoneNumberMatchStrategyImpl) :
       
    70         public CActive,
       
    71         public MVPbkContactFindObserver,
       
    72         public MVPbkSingleContactOperationObserver
       
    73     {
       
    74     public: // Construction
       
    75         static CVPbkPhoneNumberMatchStrategyImpl* NewL(
       
    76                 CVPbkPhoneNumberMatchStrategy& aParent,
       
    77                 const CVPbkPhoneNumberMatchStrategy::TConfig& aConfig,
       
    78                 CVPbkContactManager& aContactManager,
       
    79                 MVPbkContactFindObserver& aObserver);
       
    80         ~CVPbkPhoneNumberMatchStrategyImpl();
       
    81 
       
    82     public: // Interface
       
    83         void MatchL(const TDesC& aPhoneNumber);
       
    84         TInt MaxMatchDigits() const;
       
    85         TArray<MVPbkContactStore*> StoresToMatch() const;
       
    86         TBool IsSimStore( const MVPbkContactStore& aStore );
       
    87         
       
    88     private: // From CActive
       
    89         void RunL();
       
    90         void DoCancel();
       
    91         TInt RunError(TInt aError);
       
    92 
       
    93     private: // From MVPbkContactFindObserver
       
    94         void FindCompleteL(MVPbkContactLinkArray* aResults);
       
    95         void FindFailed(TInt aError);
       
    96 
       
    97     private: // From MVPbkSingleContactOperationObserver
       
    98         void VPbkSingleContactOperationComplete(
       
    99                 MVPbkContactOperationBase& aOperation,
       
   100                 MVPbkStoreContact* aContact);
       
   101         void VPbkSingleContactOperationFailed(
       
   102                 MVPbkContactOperationBase& aOperation,
       
   103                 TInt aError);
       
   104    
       
   105     private:
       
   106         /// Phone number types
       
   107         enum TNumberType { ENotInitialized, EUnknown, EDigit, EPlus, EOneZero, ETwoZeros };
       
   108         
       
   109     private: // Implementation
       
   110         CVPbkPhoneNumberMatchStrategyImpl(CVPbkPhoneNumberMatchStrategy& aParent);
       
   111         void ConstructL(
       
   112                 const CVPbkPhoneNumberMatchStrategy::TConfig& aConfig,
       
   113                 CVPbkContactManager& aContactManager,
       
   114                 MVPbkContactFindObserver& aObserver);
       
   115 
       
   116         /**
       
   117          * Searches for a store that has given URI from the list of
       
   118          * stores that the contact manager has.
       
   119          * @param aUriPtr URI of the store to search for.
       
   120          * @return The store with aUriPtr, or NULL if store was not found.
       
   121          */
       
   122         MVPbkContactStore* FindStoreL(
       
   123                 const TVPbkContactStoreUriPtr& aUriPtr);
       
   124 
       
   125         /**
       
   126          * Issues new request to be handled in RunL.
       
   127          */
       
   128         void IssueRequest();
       
   129 
       
   130         MVPbkContactLink* IsValidResultLC(MVPbkStoreContact* aContact);
       
   131 
       
   132         /**
       
   133          * Creates name tokens array
       
   134          * @param aContact which is checking, RPointerArray reference
       
   135          */
       
   136         void CreateNameTokensArrayL( MVPbkStoreContact* aContact, RPointerArray <HBufC>& aNameTokensArray );
       
   137         
       
   138         /**
       
   139          * Check if contact already exists in results array
       
   140          * @param aContact which is checking
       
   141          * @return True if contact exist or if array was empty.
       
   142          */
       
   143         TBool CheckContactDuplicationL( MVPbkStoreContact* aContact );
       
   144         
       
   145         /**
       
   146          * Gets contact's field value
       
   147          * @param aContact to get field's value from
       
   148          * @param aFieldType: EVPbkVersitNameN for Last Name 
       
   149          * EVPbkVersitNameFN for First Name
       
   150          * @return Pointer descriptor with field's value.
       
   151          */
       
   152         TPtrC NameFieldValueL( MVPbkStoreContact* aContact, TVPbkFieldTypeName aFieldType );
       
   153         
       
   154         TBool ValidateBestMatchingRulesL( const TDesC& aNumber );
       
   155         TBool CheckBestMatchingRules( const TDesC& aNumberA, TNumberType aNumberAType,
       
   156                 const TDesC& aNumberB, TNumberType aNumberBType  );
       
   157         TInt FormatAndCheckNumberType( TDes& aNumber );
       
   158         
       
   159         /**
       
   160          * Reads current store configuration from central repositiry
       
   161          * @return Array of stores or NULL if error during reading form cenrep.
       
   162         */
       
   163         CVPbkContactStoreUriArray* GetCurrentStoreConfigurationL();
       
   164         
       
   165         /**
       
   166          * If there is in the results at least one contact
       
   167          * from currently used stores in Phonebook2 it removes from results 
       
   168          * contacts from other stores
       
   169         */
       
   170         void RefineDuplicatedNumbersL();
       
   171         
       
   172         /**
       
   173          * Load number parser plugin.
       
   174         */
       
   175         void LoadNumberParserPluginL();
       
   176         
       
   177     private: // Data
       
   178         CVPbkPhoneNumberMatchStrategy& iParent;
       
   179         /// Ref: The contact manager instance to be used for searching.
       
   180         CVPbkContactManager* iContactManager;
       
   181         /// Ref: Observer for the searching process.
       
   182         MVPbkContactFindObserver* iObserver;
       
   183         /// Own: The find operation that is currently ongoing.
       
   184         MVPbkContactOperationBase* iOperation;
       
   185         /// Maximum number of matched digits.
       
   186         TInt iMaxMatchDigits;
       
   187         /// Flags to configure matching process, @see TVPbkPhoneNumberMatchFlags
       
   188         TUint32 iMatchFlags;
       
   189 
       
   190         /// Own: Array of stores that are used in matching.
       
   191         RPointerArray<MVPbkContactStore> iStoresToMatch;
       
   192         /// Own: Phone number that is being matched.
       
   193         HBufC* iPhoneNumber;
       
   194         /// Own: Intermediate results of the matching process.
       
   195         CVPbkContactLinkArray* iWorkingResults;
       
   196         /// Own: Final results of the matching process.
       
   197         CVPbkContactLinkArray* iResults;
       
   198         /// iWorkingResults index of current contact retrieval
       
   199         TInt iCurrentContact;
       
   200 
       
   201         /// Own: Currently retrieved contact
       
   202         MVPbkStoreContact* iStoreContact;
       
   203         /// Own: Field type selector
       
   204         CVPbkFieldTypeSelector* iFieldTypeSelector;
       
   205         /// Own: A filtered and sorted collection of Virtual Phonebook contact fields.
       
   206         CVPbkFieldFilter* iFieldFilter;
       
   207 
       
   208         /// Active object states
       
   209         enum TState { EMatch, ERemoveDuplicates, ERefineSearch, EComplete };
       
   210         /// Active object current state
       
   211         TState iState;
       
   212         
       
   213         /// Own: First Name field type selector
       
   214         CVPbkFieldTypeSelector* iFirstNameSelector;
       
   215         /// Own: Last Name field type selector
       
   216         CVPbkFieldTypeSelector* iLastNameSelector;
       
   217         /// Own: Array of tokens gotten from first and last name fields of first matched contact
       
   218         RPointerArray <HBufC> iNameTokensArray;
       
   219         /// Own: Array of tokens gotten from first and last name fields of contact
       
   220         RPointerArray <HBufC> iTempNameTokensArray;
       
   221         /// Indicates if all contact in iResult are the same
       
   222         TBool iDoubledContacts;
       
   223         /// type of iPhoneNumber
       
   224         TNumberType iPhoneNumberType;
       
   225         // Own: parser
       
   226         CContactPhoneNumberParser* iParser;
       
   227     };
       
   228 
       
   229 CVPbkPhoneNumberMatchStrategyImpl::CVPbkPhoneNumberMatchStrategyImpl(
       
   230         CVPbkPhoneNumberMatchStrategy& aParent) :
       
   231     CActive(CActive::EPriorityIdle),
       
   232     iParent(aParent)
       
   233     {
       
   234     CActiveScheduler::Add(this);
       
   235     }
       
   236 
       
   237 inline void CVPbkPhoneNumberMatchStrategyImpl::ConstructL(
       
   238         const CVPbkPhoneNumberMatchStrategy::TConfig& aConfig,
       
   239         CVPbkContactManager& aContactManager,
       
   240         MVPbkContactFindObserver& aObserver)
       
   241     {
       
   242     iContactManager = &aContactManager;
       
   243     iObserver = &aObserver;
       
   244 
       
   245     iMaxMatchDigits = aConfig.iMaxMatchDigits;
       
   246     iMatchFlags = aConfig.iMatchFlags;
       
   247 
       
   248     const TInt uriCount = aConfig.iUriPriorities.Count();
       
   249     for (TInt i = 0; i < uriCount; ++i)
       
   250         {
       
   251         MVPbkContactStore* store = FindStoreL(aConfig.iUriPriorities[i]);
       
   252         if (store)
       
   253             {
       
   254             iStoresToMatch.AppendL(store);
       
   255             }
       
   256         }
       
   257 
       
   258     VPbkEngUtils::RLocalizedResourceFile resFile;
       
   259     resFile.OpenLC(iContactManager->FsSession(),
       
   260                    KVPbkRomFileDrive,
       
   261                    KDC_RESOURCE_FILES_DIR,
       
   262                    KVPbkFieldTypeSelectorsResFileName);
       
   263     HBufC8* selectorBuf = resFile.AllocReadLC(R_VPBK_PHONE_NUMBER_SELECTOR);
       
   264     TResourceReader resReader;
       
   265     resReader.SetBuffer(selectorBuf);
       
   266 
       
   267     iFieldTypeSelector = CVPbkFieldTypeSelector::NewL(resReader, iContactManager->FieldTypes());
       
   268 
       
   269     CleanupStack::PopAndDestroy( selectorBuf );
       
   270     
       
   271     if ( iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkDuplicatedContactsMatchFlag )
       
   272     	{ 
       
   273 	    HBufC8* firstNameSelectorBuf = resFile.AllocReadLC( R_VPBK_FIRST_NAME_SELECTOR );
       
   274 	    resReader.SetBuffer( firstNameSelectorBuf );
       
   275 	    iFirstNameSelector = CVPbkFieldTypeSelector::NewL( resReader, iContactManager->FieldTypes() );
       
   276 	    CleanupStack::PopAndDestroy( firstNameSelectorBuf );
       
   277 	
       
   278 	    HBufC8* lastNameSelectorBuf = resFile.AllocReadLC( R_VPBK_LAST_NAME_SELECTOR );
       
   279 	    resReader.SetBuffer( lastNameSelectorBuf );
       
   280 	    iLastNameSelector = CVPbkFieldTypeSelector::NewL( resReader, iContactManager->FieldTypes() );
       
   281 	    CleanupStack::PopAndDestroy( lastNameSelectorBuf );
       
   282     	}
       
   283 
       
   284     CleanupStack::PopAndDestroy( &resFile );
       
   285     
       
   286     LoadNumberParserPluginL();
       
   287     }
       
   288 
       
   289 CVPbkPhoneNumberMatchStrategyImpl* CVPbkPhoneNumberMatchStrategyImpl::NewL(
       
   290         CVPbkPhoneNumberMatchStrategy& aParent,
       
   291         const CVPbkPhoneNumberMatchStrategy::TConfig& aConfig,
       
   292         CVPbkContactManager& aContactManager,
       
   293         MVPbkContactFindObserver& aObserver)
       
   294     {
       
   295     CVPbkPhoneNumberMatchStrategyImpl* self =
       
   296             new(ELeave) CVPbkPhoneNumberMatchStrategyImpl(aParent);
       
   297     CleanupStack::PushL(self);
       
   298     self->ConstructL(aConfig, aContactManager, aObserver);
       
   299     CleanupStack::Pop(self);
       
   300     return self;
       
   301     }
       
   302 
       
   303 CVPbkPhoneNumberMatchStrategyImpl::~CVPbkPhoneNumberMatchStrategyImpl()
       
   304     {
       
   305     Cancel();
       
   306     
       
   307     delete iFieldFilter;
       
   308     delete iFieldTypeSelector;
       
   309     delete iWorkingResults;
       
   310     delete iResults;
       
   311     delete iStoreContact;
       
   312     delete iPhoneNumber;
       
   313     delete iOperation;
       
   314     delete iFirstNameSelector;
       
   315     delete iLastNameSelector;
       
   316     iNameTokensArray.ResetAndDestroy();
       
   317     iTempNameTokensArray.ResetAndDestroy();
       
   318     iStoresToMatch.Close();
       
   319     delete iParser;
       
   320     REComSession::FinalClose();
       
   321     }
       
   322 
       
   323 void CVPbkPhoneNumberMatchStrategyImpl::MatchL(const TDesC& aPhoneNumber)
       
   324     {
       
   325     HBufC* phoneNumber = aPhoneNumber.AllocL();
       
   326     delete iPhoneNumber;
       
   327     iPhoneNumber = phoneNumber;
       
   328     iPhoneNumberType = ENotInitialized;
       
   329     
       
   330     if ( iWorkingResults )
       
   331         {
       
   332         iWorkingResults->ResetAndDestroy();
       
   333         }                
       
   334     if ( iResults )
       
   335         {
       
   336         iResults->ResetAndDestroy();
       
   337         }                
       
   338     iCurrentContact = KMagicNumber;
       
   339     
       
   340     if ( iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkDuplicatedContactsMatchFlag )
       
   341     	{
       
   342     	iDoubledContacts = ETrue;
       
   343     	}
       
   344     else
       
   345     	{
       
   346     	iDoubledContacts = EFalse;
       
   347     	}
       
   348     iState = EMatch;
       
   349     IssueRequest();
       
   350     }
       
   351 
       
   352 
       
   353 void CVPbkPhoneNumberMatchStrategyImpl::IssueRequest()
       
   354     {
       
   355     TRequestStatus* status = &iStatus;
       
   356     User::RequestComplete(status, KErrNone);
       
   357     SetActive();
       
   358     }
       
   359 
       
   360 void CVPbkPhoneNumberMatchStrategyImpl::RunL()
       
   361     {
       
   362     switch (iState)
       
   363         {
       
   364         case EMatch:
       
   365             {
       
   366             MVPbkContactOperation* operation = iParent.CreateFindOperationLC(*iPhoneNumber);
       
   367             if (operation)
       
   368                 {
       
   369                 operation->StartL();
       
   370                 CleanupStack::Pop(); // operation
       
   371                 delete iOperation;
       
   372                 iOperation = operation;
       
   373                 }
       
   374             else
       
   375                 {
       
   376                 // all needed operations are done if any
       
   377                 iState = ERemoveDuplicates;
       
   378                 IssueRequest();
       
   379                 }
       
   380             break;
       
   381             }
       
   382         case ERemoveDuplicates:
       
   383             {
       
   384             const TInt count = iWorkingResults ? iWorkingResults->Count() : 0;
       
   385             CVPbkContactLinkArray* results = CVPbkContactLinkArray::NewLC();
       
   386             for (TInt i = 0; i < count; ++i)
       
   387                 {
       
   388                 MVPbkContactLink* link = iWorkingResults->At(i).CloneLC();
       
   389                 if (results->Find(*link) == KErrNotFound)
       
   390                     {
       
   391                     results->AppendL(link);
       
   392                     CleanupStack::Pop(); // link
       
   393                     }
       
   394                 else
       
   395                     {
       
   396                     CleanupStack::PopAndDestroy(); // link
       
   397                     }
       
   398                 }
       
   399             CleanupStack::Pop(results);
       
   400             delete iWorkingResults;
       
   401             iWorkingResults = results;
       
   402             iState = ERefineSearch;
       
   403             iCurrentContact = 0;
       
   404             IssueRequest();
       
   405             break;
       
   406             }
       
   407         case ERefineSearch:
       
   408             {
       
   409             if (!iResults)
       
   410                 {
       
   411                 iResults = CVPbkContactLinkArray::NewL();
       
   412                 }
       
   413             
       
   414             MVPbkContactLink* result = IsValidResultLC( iStoreContact );
       
   415             if ( result )
       
   416                 {
       
   417                 iResults->AppendL( result );
       
   418                 CleanupStack::Pop(); // MVPbkContactLink
       
   419                 
       
   420                 if ( iDoubledContacts )
       
   421                     {
       
   422                     iDoubledContacts = CheckContactDuplicationL( iStoreContact );
       
   423                     }
       
   424                 }
       
   425 
       
   426             delete iStoreContact;
       
   427             iStoreContact = NULL;
       
   428                 
       
   429             const TInt count = iWorkingResults ? iWorkingResults->Count() : 0;
       
   430             if (iCurrentContact < count &&                 
       
   431                 !( iResults->Count() > 0 && 
       
   432                         (iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkStopOnFirstMatchFlag)))
       
   433                 {
       
   434                 const MVPbkContactLink& link = iWorkingResults->At(iCurrentContact);
       
   435                 delete iOperation;
       
   436                 iOperation = NULL;
       
   437                 iOperation = iContactManager->RetrieveContactL(link, *this);
       
   438                 ++iCurrentContact;
       
   439                 }
       
   440             else
       
   441                 {
       
   442                 iState = EComplete;
       
   443                 IssueRequest();
       
   444                 }
       
   445             break;
       
   446             }
       
   447         case EComplete:
       
   448             {
       
   449             iNameTokensArray.ResetAndDestroy();
       
   450             iTempNameTokensArray.ResetAndDestroy();
       
   451             if ( iDoubledContacts && iResults->Count() )
       
   452                 {
       
   453                 CVPbkContactLinkArray* results = CVPbkContactLinkArray::NewLC();
       
   454                 MVPbkContactLink* link = iResults->At(0).CloneLC(); // first element
       
   455                 results->AppendL( link );
       
   456                 CleanupStack::Pop( 2, results ); // results, link
       
   457                 delete iResults;
       
   458                 iResults = results;
       
   459                 }
       
   460 
       
   461             if ( iResults->Count() > 1 )
       
   462                 {
       
   463                 RefineDuplicatedNumbersL();
       
   464                 }
       
   465 
       
   466             CVPbkContactLinkArray* results = iResults;
       
   467             iResults = NULL;            
       
   468             iObserver->FindCompleteL( results );
       
   469             break;
       
   470             }
       
   471         default:
       
   472             {
       
   473             // This case should not be possible
       
   474             User::Leave( KErrArgument );
       
   475             break;
       
   476             }
       
   477         }
       
   478     }
       
   479 
       
   480 void CVPbkPhoneNumberMatchStrategyImpl::DoCancel()
       
   481     {
       
   482     }
       
   483 
       
   484 TInt CVPbkPhoneNumberMatchStrategyImpl::RunError(TInt aError)
       
   485     {
       
   486     iObserver->FindFailed(aError);
       
   487     return KErrNone;
       
   488     }
       
   489 
       
   490 inline MVPbkContactStore* CVPbkPhoneNumberMatchStrategyImpl::FindStoreL(
       
   491         const TVPbkContactStoreUriPtr& aUriPtr)
       
   492     {
       
   493     const TInt storeCount = iContactManager->ContactStoresL().Count();
       
   494     for (TInt i = 0; i < storeCount; ++i)
       
   495         {
       
   496         MVPbkContactStore& store = iContactManager->ContactStoresL().At(i);
       
   497         if (store.StoreProperties().Uri().Compare(
       
   498                     aUriPtr,
       
   499                     TVPbkContactStoreUriPtr::EContactStoreUriAllComponents) == 0)
       
   500             {
       
   501             return &store;
       
   502             }
       
   503         }
       
   504     return NULL;
       
   505     }
       
   506 
       
   507 void CVPbkPhoneNumberMatchStrategyImpl::FindCompleteL(MVPbkContactLinkArray* aResults)
       
   508     {
       
   509     // This function called by operation which is created in 
       
   510     // iParent.CreateFindOperationLC
       
   511     if (aResults)
       
   512         {
       
   513         CleanupDeletePushL( aResults ); // Take ownership
       
   514         
       
   515         if (!iWorkingResults)
       
   516             {
       
   517             iWorkingResults = CVPbkContactLinkArray::NewL();
       
   518             }
       
   519         const TInt count = aResults->Count();
       
   520         for (TInt i = 0; i < count; ++i)
       
   521             {
       
   522             MVPbkContactLink* link = aResults->At(i).CloneLC();
       
   523             iWorkingResults->AppendL(link);
       
   524             CleanupStack::Pop(); // link
       
   525             }
       
   526 
       
   527         CleanupStack::PopAndDestroy(); // aResults
       
   528         }
       
   529     IssueRequest();
       
   530     }
       
   531 
       
   532 void CVPbkPhoneNumberMatchStrategyImpl::FindFailed(TInt aError)
       
   533     {
       
   534     iObserver->FindFailed(aError);
       
   535     }
       
   536 
       
   537 void CVPbkPhoneNumberMatchStrategyImpl::VPbkSingleContactOperationComplete(
       
   538         MVPbkContactOperationBase& aOperation,
       
   539         MVPbkStoreContact* aContact)
       
   540     {
       
   541     if (iOperation == &aOperation)
       
   542         {
       
   543         delete iOperation;
       
   544         iOperation = NULL;
       
   545 
       
   546         iStoreContact = aContact;
       
   547         IssueRequest();
       
   548         }
       
   549     }
       
   550 
       
   551 void CVPbkPhoneNumberMatchStrategyImpl::VPbkSingleContactOperationFailed(
       
   552         MVPbkContactOperationBase& aOperation,
       
   553         TInt aError)
       
   554     {
       
   555     if (iOperation == &aOperation)
       
   556         {
       
   557         delete iOperation;
       
   558         iOperation = NULL;
       
   559 
       
   560         iObserver->FindFailed(aError);
       
   561         }
       
   562     }
       
   563 
       
   564 TInt CVPbkPhoneNumberMatchStrategyImpl::MaxMatchDigits() const
       
   565     {
       
   566     return iMaxMatchDigits;
       
   567     }
       
   568 
       
   569 TArray<MVPbkContactStore*> CVPbkPhoneNumberMatchStrategyImpl::StoresToMatch() const
       
   570     {
       
   571     return iStoresToMatch.Array();
       
   572     }
       
   573 
       
   574 MVPbkContactLink* CVPbkPhoneNumberMatchStrategyImpl::IsValidResultLC(
       
   575         MVPbkStoreContact* aContact)
       
   576     {
       
   577     MVPbkContactLink* result = NULL;
       
   578 
       
   579     if (!(iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkExactMatchFlag)
       
   580             && !(iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkBestMatchingFlag))
       
   581         {
       
   582         // If exact match is not needed we will accept the contact as valid
       
   583         // if it is not NULL
       
   584         if ( aContact )
       
   585             {
       
   586             result = aContact->CreateLinkLC();
       
   587             }        
       
   588         }
       
   589     else if (aContact)
       
   590         {
       
   591         TPtrC matchedNumber = iPhoneNumber->Des().
       
   592                 Right(Min(iPhoneNumber->Length(), iMaxMatchDigits));
       
   593 
       
   594         CVPbkFieldFilter::TConfig config(aContact->Fields(), iFieldTypeSelector);
       
   595         if (!iFieldFilter)
       
   596             {
       
   597             iFieldFilter = CVPbkFieldFilter::NewL(config);
       
   598             }
       
   599         else
       
   600             {
       
   601             iFieldFilter->ResetL(config);
       
   602             }
       
   603         const TInt count = iFieldFilter->FieldCount();
       
   604         for (TInt i = 0; i < count; ++i)
       
   605             {
       
   606             MVPbkContactFieldData& data = iFieldFilter->FieldAt(i).FieldData();
       
   607             if (data.DataType() == EVPbkFieldStorageTypeText)
       
   608                 {
       
   609                 const TDesC& dataText = MVPbkContactFieldTextData::Cast(data).Text();
       
   610                 if (iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkExactMatchFlag)
       
   611                     {
       
   612                     TPtrC dataTextPtr = dataText.Right(Min(dataText.Length(), iMaxMatchDigits));
       
   613                     if (dataTextPtr == matchedNumber)
       
   614                         {
       
   615                         result = iFieldFilter->FieldAt(i).CreateLinkLC();
       
   616                         break;
       
   617                         }
       
   618                     }
       
   619                 else if (iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkBestMatchingFlag
       
   620                             && ValidateBestMatchingRulesL(dataText))
       
   621                     {
       
   622                     result = aContact->CreateLinkLC();
       
   623                     break;
       
   624                     }
       
   625                 }
       
   626             }
       
   627         }
       
   628     return result;
       
   629     }
       
   630 
       
   631 TBool CVPbkPhoneNumberMatchStrategyImpl::CheckContactDuplicationL(
       
   632         MVPbkStoreContact* aContact )
       
   633     {
       
   634 
       
   635     if ( !aContact )
       
   636         {
       
   637         return ETrue;
       
   638         }
       
   639     
       
   640     if ( aContact && iCurrentContact == 1 )
       
   641         {
       
   642         CreateNameTokensArrayL( aContact, iNameTokensArray );
       
   643         return ETrue;
       
   644         }
       
   645     else 
       
   646         {
       
   647         iTempNameTokensArray.ResetAndDestroy();
       
   648         CreateNameTokensArrayL( aContact, iTempNameTokensArray );
       
   649         TInt count = iNameTokensArray.Count();
       
   650         if ( iNameTokensArray.Count() != iTempNameTokensArray.Count() )
       
   651         	{
       
   652         	return EFalse;
       
   653         	}
       
   654         else
       
   655         	{
       
   656         	TInt result = 0;
       
   657         	for ( TInt i = 0; i < count; i++ )
       
   658         		{
       
   659         		HBufC* token = iNameTokensArray[i];
       
   660         		TInt tempCount = iTempNameTokensArray.Count();
       
   661             	for ( TInt j = 0; j < tempCount; j++ )
       
   662             		{
       
   663             		result = token->Compare( *( iTempNameTokensArray[j] ) );
       
   664                 	if ( !result )
       
   665                 		{
       
   666                 		HBufC* removedToken = iTempNameTokensArray[j];
       
   667                 		iTempNameTokensArray.Remove( j );
       
   668                 		delete removedToken;
       
   669                 		break;
       
   670                 		}
       
   671             		}
       
   672             	if ( result )
       
   673             		{
       
   674             		return EFalse;
       
   675             		}
       
   676         		}
       
   677         	}
       
   678         return ETrue;
       
   679         }
       
   680     }
       
   681 
       
   682 void CVPbkPhoneNumberMatchStrategyImpl::CreateNameTokensArrayL( MVPbkStoreContact* aContact,
       
   683 										RPointerArray <HBufC>& aNameTokensArray )
       
   684 	{
       
   685     TPtrC firstName = NameFieldValueL( aContact, EVPbkVersitNameFN );
       
   686     TLex lexer;
       
   687     lexer.Assign( firstName );
       
   688     
       
   689     TPtrC ptr;
       
   690     TInt len = 0;
       
   691     while( ETrue )
       
   692         {
       
   693         ptr.Set( lexer.NextToken() );
       
   694         
       
   695         len = ptr.Length();
       
   696         if ( len )
       
   697             {
       
   698             HBufC* token = ptr.AllocLC();
       
   699             aNameTokensArray.AppendL( token );
       
   700             CleanupStack::Pop( token );
       
   701             }
       
   702         else
       
   703             {
       
   704             break;
       
   705             }
       
   706         } 
       
   707 
       
   708     TPtrC lastName = NameFieldValueL( aContact, EVPbkVersitNameN );
       
   709 
       
   710     lexer.Assign( lastName );
       
   711     
       
   712     len = 0;
       
   713     while( ETrue )
       
   714         {
       
   715         ptr.Set( lexer.NextToken() );
       
   716         
       
   717         len = ptr.Length();
       
   718         if ( len )
       
   719             {
       
   720             HBufC* token = ptr.AllocLC();
       
   721             aNameTokensArray.AppendL( token );
       
   722             CleanupStack::Pop( token );
       
   723             }
       
   724         else
       
   725             {
       
   726             break;
       
   727             }
       
   728         }
       
   729 	}
       
   730 
       
   731 TPtrC CVPbkPhoneNumberMatchStrategyImpl::NameFieldValueL( 
       
   732         MVPbkStoreContact* aContact, TVPbkFieldTypeName aFieldType )
       
   733     {
       
   734     if ( aContact )
       
   735         {
       
   736         CVPbkFieldFilter::TConfig config( aContact->Fields() );
       
   737         if ( aFieldType == EVPbkVersitNameFN )
       
   738             {
       
   739             config.iFieldSelector = iFirstNameSelector;
       
   740             }
       
   741         else if ( aFieldType == EVPbkVersitNameN )
       
   742             {
       
   743             config.iFieldSelector = iLastNameSelector;
       
   744             }
       
   745         else
       
   746             {
       
   747             return KNullDesC();
       
   748             }
       
   749         
       
   750         if (!iFieldFilter)
       
   751             {
       
   752             iFieldFilter = CVPbkFieldFilter::NewL(config);
       
   753             }
       
   754         else
       
   755             {
       
   756             iFieldFilter->ResetL(config);
       
   757             }
       
   758         const TInt count = iFieldFilter->FieldCount();
       
   759         for (TInt i = 0; i < count; ++i)
       
   760             {
       
   761             MVPbkContactFieldData& data = iFieldFilter->FieldAt(i).FieldData();
       
   762             if (data.DataType() == EVPbkFieldStorageTypeText)
       
   763                 {
       
   764                 return  MVPbkContactFieldTextData::Cast(data).Text();
       
   765                 }
       
   766             }
       
   767         return KNullDesC();
       
   768         }
       
   769     else
       
   770         {
       
   771         return KNullDesC();
       
   772         }
       
   773     }
       
   774 
       
   775 // Removes non-digit chars except plus form the beginning
       
   776 // Checks if number matches to one of defined types
       
   777 //
       
   778 TInt CVPbkPhoneNumberMatchStrategyImpl::FormatAndCheckNumberType( TDes& aNumber )
       
   779     {
       
   780     _LIT( KOneZeroPattern, "0*" );
       
   781     _LIT( KTwoZerosPattern, "00*" );
       
   782     _LIT( KPlusPattern, "+*" );
       
   783     _LIT( KPlusString, "+" );
       
   784     const TChar KPlus = TChar('+');
       
   785     const TChar KZero = TChar('0');
       
   786     const TChar KAsterisk = TChar('*');
       
   787     const TChar KHash = TChar('#');
       
   788     
       
   789     HBufC* numberBuf = HBufC::NewL( aNumber.Length() );
       
   790     TPtr number = numberBuf->Des();
       
   791     if ( iParser )
       
   792         {
       
   793         iParser->ExtractRawNumber( aNumber, number );
       
   794         }
       
   795     TInt pos = aNumber.Find( number );
       
   796     
       
   797     if ( pos > 0 && aNumber[pos-1] == KPlus )
       
   798         {
       
   799         number.Insert( 0, KPlusString );
       
   800         }
       
   801     
       
   802     if ( number.Length() > 0)
       
   803         {
       
   804         aNumber.Copy( number );
       
   805         }
       
   806     delete numberBuf;
       
   807     
       
   808 	TInt format;
       
   809 	
       
   810     if ( !aNumber.Match( KTwoZerosPattern ) && aNumber.Length() > 2 && aNumber[2] != KZero )
       
   811         {
       
   812         format = ETwoZeros;
       
   813         }
       
   814     else if ( !aNumber.Match( KOneZeroPattern )&& aNumber.Length() > 1 && aNumber[1] != KZero )
       
   815         {
       
   816         format = EOneZero;
       
   817         }
       
   818     else if ( !aNumber.Match( KPlusPattern ) && aNumber.Length() > 1 && aNumber[1] != KZero )
       
   819         {
       
   820         format = EPlus;
       
   821         }
       
   822     else if ( aNumber.Length() > 0 && aNumber[0] != KZero && ( ( TChar ) aNumber[0] ).IsDigit() )
       
   823         {
       
   824         format = EDigit;
       
   825         }
       
   826 	else
       
   827 		{
       
   828         format = EUnknown;
       
   829 	    }
       
   830 
       
   831     return format;
       
   832     }
       
   833 
       
   834 TBool CVPbkPhoneNumberMatchStrategyImpl::ValidateBestMatchingRulesL( const TDesC& aNumber )
       
   835     {
       
   836     if ( iPhoneNumberType == ENotInitialized )
       
   837         {
       
   838         TPtr16 phoneNumber = iPhoneNumber->Des();
       
   839         iPhoneNumberType = ( TNumberType ) FormatAndCheckNumberType( phoneNumber );
       
   840         }
       
   841     
       
   842     HBufC* number = aNumber.AllocLC();
       
   843     TPtr16 phoneNumber = number->Des();
       
   844     TNumberType numberType = ( TNumberType ) FormatAndCheckNumberType( phoneNumber );
       
   845 
       
   846     TBool match = ( !phoneNumber.Compare( *iPhoneNumber ) ||
       
   847                   CheckBestMatchingRules( *iPhoneNumber, iPhoneNumberType, *number, numberType  ) ||
       
   848                   CheckBestMatchingRules( *number, numberType, *iPhoneNumber, iPhoneNumberType  ) );
       
   849 
       
   850     CleanupStack::PopAndDestroy( number );
       
   851 
       
   852     return match;
       
   853     }
       
   854 
       
   855 TBool CVPbkPhoneNumberMatchStrategyImpl::CheckBestMatchingRules(
       
   856         const TDesC& aNumberA, TNumberType aNumberAType,
       
   857         const TDesC& aNumberB, TNumberType aNumberBType  )
       
   858     {
       
   859     TBool result = EFalse;
       
   860     
       
   861     // Rules for matching not identical numbers
       
   862     // Rules details are presented in Best_Number_Matching_Algorithm_Description.doc
       
   863     
       
   864     // rule International-International 1
       
   865     if ( !result && aNumberAType == EPlus && aNumberBType == ETwoZeros )
       
   866         {
       
   867         TPtrC numberA = aNumberA.Right( aNumberA.Length() - 1 );
       
   868         TPtrC numberB = aNumberB.Right( aNumberB.Length() - 2 );
       
   869         result = !( numberA.Compare( numberB ) );
       
   870         if ( result )
       
   871             {
       
   872             return result;
       
   873             }
       
   874         }
       
   875 
       
   876     // rule International-International 2
       
   877     if ( aNumberAType == EPlus && aNumberBType == EDigit )
       
   878         {
       
   879         TPtrC numberA = aNumberA.Right( aNumberA.Length() - 1 );
       
   880         if ( numberA.Length() < aNumberB.Length() )
       
   881             {
       
   882             TPtrC numberB = aNumberB.Right( numberA.Length() );
       
   883             result = !( numberA.Compare( numberB ) );
       
   884             if ( result )
       
   885                 {
       
   886                 return result;
       
   887                 }
       
   888             }
       
   889         }
       
   890 
       
   891     // rule International-International 3
       
   892     if ( aNumberAType == ETwoZeros && aNumberBType == EDigit )
       
   893         {
       
   894         TPtrC numberA = aNumberA.Right( aNumberA.Length() - 2 );
       
   895         if ( numberA.Length() < aNumberB.Length() )
       
   896             {
       
   897             TPtrC numberB = aNumberB.Right( numberA.Length() );
       
   898             result = !( numberA.Compare( numberB ) );
       
   899             if ( result )
       
   900                 {
       
   901                 return result;
       
   902                 }
       
   903             }
       
   904         }
       
   905 
       
   906     // rule International-Operator 1
       
   907     if ( aNumberAType == EOneZero && aNumberBType == EPlus
       
   908             || aNumberAType == EDigit && aNumberBType == EPlus )
       
   909         {
       
   910         TPtrC numberA;
       
   911         if ( aNumberAType == EOneZero )
       
   912             {
       
   913             numberA.Set( aNumberA.Right( aNumberA.Length() - 1 ) );
       
   914             }
       
   915         else
       
   916             {
       
   917             numberA.Set( aNumberA );
       
   918             }
       
   919         if ( numberA.Length() < aNumberB.Length() - 1 )
       
   920             {
       
   921             TPtrC numberB = aNumberB.Right( numberA.Length() );
       
   922             result = !( numberA.Compare( numberB ) );
       
   923             if ( result )
       
   924                 {
       
   925                 return result;
       
   926                 }
       
   927             }
       
   928         }
       
   929 
       
   930     // rule International-Operator 2
       
   931     if ( aNumberAType == EOneZero && aNumberBType == ETwoZeros
       
   932             || aNumberAType == EDigit && aNumberBType == ETwoZeros )
       
   933         {
       
   934         TPtrC numberA;
       
   935         if ( aNumberAType == EOneZero )
       
   936             {
       
   937             numberA.Set( aNumberA.Right( aNumberA.Length() - 1 ) );
       
   938             }
       
   939         else
       
   940             {
       
   941             numberA.Set( aNumberA );
       
   942             }
       
   943         if ( numberA.Length() < aNumberB.Length() - 2 )
       
   944             {
       
   945             TPtrC numberB = aNumberB.Right( numberA.Length() );
       
   946             result = !( numberA.Compare( numberB ) );
       
   947             if ( result )
       
   948                 {
       
   949                 return result;
       
   950                 }
       
   951             }
       
   952         }
       
   953 
       
   954     // rule International-Operator 3
       
   955     if ( aNumberAType == EOneZero && aNumberBType == EDigit
       
   956             || aNumberAType == EDigit && aNumberBType == EDigit )
       
   957         {
       
   958         TPtrC numberA;
       
   959         if ( aNumberAType == EOneZero )
       
   960             {
       
   961             numberA.Set( aNumberA.Right( aNumberA.Length() - 1 ) );
       
   962             }
       
   963         else
       
   964             {
       
   965             numberA.Set( aNumberA );
       
   966             }
       
   967         if ( numberA.Length() < aNumberB.Length() )
       
   968             {
       
   969             TPtrC numberB = aNumberB.Right( numberA.Length() );
       
   970             result = !( numberA.Compare( numberB ) );
       
   971             if ( result )
       
   972                 {
       
   973                 return result;
       
   974                 }
       
   975             }
       
   976         }
       
   977 
       
   978     // rule Operator-Operator 1
       
   979     if ( aNumberAType == EOneZero && aNumberBType == EDigit )
       
   980         {
       
   981         TPtrC numberA = aNumberA.Right( aNumberA.Length() - 1 );
       
   982         result = !( numberA.Compare( aNumberB ) );
       
   983             {
       
   984             if ( result )
       
   985                 {
       
   986                 return result;
       
   987                 }
       
   988             }
       
   989         }
       
   990     
       
   991     // rule North America Numbering Plan 1
       
   992     if ( aNumberAType == EDigit && aNumberBType == EPlus )
       
   993         {
       
   994         TPtrC numberB = aNumberB.Right( aNumberB.Length() - 1 );
       
   995         result = !( aNumberA.Compare( numberB ) );
       
   996             {
       
   997             if ( result )
       
   998                 {
       
   999                 return result;
       
  1000                 }
       
  1001             }
       
  1002         }
       
  1003 
       
  1004     // More exceptional acceptance rules can be added here
       
  1005 	// Keep rules updated in the document Best_Number_Matching_Algorithm_Description.doc
       
  1006 
       
  1007     return result;
       
  1008     }
       
  1009 
       
  1010 CVPbkContactStoreUriArray* CVPbkPhoneNumberMatchStrategyImpl::GetCurrentStoreConfigurationL()
       
  1011     {
       
  1012     CRepository* repository = CRepository::NewL( TUid::Uid( KCRUidPhonebookStoreConfiguration ) );
       
  1013     CleanupStack::PushL( repository );
       
  1014     CVPbkContactStoreUriArray* result = CVPbkContactStoreUriArray::NewLC();
       
  1015 
       
  1016     RArray<TUint32> configurationKeys;
       
  1017     CleanupClosePushL( configurationKeys );
       
  1018 
       
  1019     repository->FindL( KPhonebookCurrentConfigurationPartialKey,
       
  1020             KPhonebookCurrentConfigurationMask, configurationKeys );
       
  1021 
       
  1022     HBufC* buffer = HBufC::NewLC( KInitialStoreUriSize );
       
  1023     const TInt keyCount = configurationKeys.Count();
       
  1024     TInt ret = KErrNone;
       
  1025     for ( TInt i = 0; i < keyCount; ++i )
       
  1026         {
       
  1027         TPtr ptr = buffer->Des();
       
  1028         ptr.Zero();
       
  1029         TInt actualSize = 0;
       
  1030         ret = repository->Get( configurationKeys[i], ptr, actualSize );
       
  1031         if ( ret == KErrOverflow )
       
  1032             {
       
  1033             CleanupStack::PopAndDestroy(); // buffer
       
  1034             buffer = HBufC::NewLC( actualSize );
       
  1035             ptr.Set( buffer->Des() );
       
  1036             ret = repository->Get( configurationKeys[i], ptr );
       
  1037             }
       
  1038         
       
  1039         if ( ret != KErrNone )
       
  1040             {
       
  1041             break;
       
  1042             }
       
  1043         
       
  1044         if( !result->IsIncluded( TVPbkContactStoreUriPtr( ptr ) ) )  // Only append if the uri is not yet included
       
  1045             {
       
  1046             result->AppendL( ptr );
       
  1047             }
       
  1048         }
       
  1049     CleanupStack::PopAndDestroy( buffer );
       
  1050     CleanupStack::PopAndDestroy( &configurationKeys );
       
  1051     CleanupStack::Pop( result );
       
  1052     CleanupStack::PopAndDestroy( repository );
       
  1053     
       
  1054     if ( ret != KErrNone )
       
  1055         {
       
  1056         delete result;
       
  1057         result = NULL;
       
  1058         }
       
  1059     return result;
       
  1060     }
       
  1061 
       
  1062 void CVPbkPhoneNumberMatchStrategyImpl::RefineDuplicatedNumbersL()
       
  1063     {
       
  1064     CVPbkContactStoreUriArray* stores = GetCurrentStoreConfigurationL();
       
  1065     if ( !stores )
       
  1066         {
       
  1067         return;
       
  1068         }
       
  1069     CleanupStack::PushL( stores );
       
  1070     
       
  1071     TInt storesCount = stores->Count();
       
  1072     if ( storesCount )
       
  1073         {
       
  1074         TInt linksCount = iResults->Count();
       
  1075         // check if there is in the results at least one contact
       
  1076         // from currently used stores
       
  1077         TBool isFromUsedStore = EFalse;
       
  1078         for ( TInt i = 0; i < linksCount; i++ )
       
  1079             {
       
  1080             const MVPbkContactStoreProperties& linkStoreProp = 
       
  1081                 iResults->At( i ).ContactStore().StoreProperties();
       
  1082 
       
  1083             for ( TInt j = 0; j < storesCount; j++ )
       
  1084                 {
       
  1085                 if ( !linkStoreProp.Uri().UriDes().Compare( ( *stores )[j].UriDes() ) )
       
  1086                     {
       
  1087                     isFromUsedStore = ETrue;
       
  1088                     break;
       
  1089                     }
       
  1090                 }
       
  1091             if ( isFromUsedStore )
       
  1092                 {
       
  1093                 break;
       
  1094                 }
       
  1095             }
       
  1096         // remove from results contacts from not used stores
       
  1097         if ( isFromUsedStore )
       
  1098             {
       
  1099             for ( TInt i = 0; i < linksCount; i++ )
       
  1100                 {
       
  1101                 TBool remove = ETrue;
       
  1102                 const MVPbkContactStoreProperties& linkStoreProp = 
       
  1103                     iResults->At( i ).ContactStore().StoreProperties();
       
  1104                 
       
  1105                 for ( TInt j = 0; j < storesCount; j++ )
       
  1106                     {
       
  1107                     if ( !linkStoreProp.Uri().UriDes().Compare( ( *stores )[j].UriDes() ) )
       
  1108                         {
       
  1109                         remove = EFalse;
       
  1110                         break;
       
  1111                         }
       
  1112                     }
       
  1113                 if ( remove )
       
  1114                     {
       
  1115                     iResults->Delete( i );
       
  1116                     linksCount--;
       
  1117                     i--;
       
  1118                     }
       
  1119                 }
       
  1120             }
       
  1121         }
       
  1122     CleanupStack::PopAndDestroy( stores );
       
  1123     }
       
  1124 
       
  1125 TBool CVPbkPhoneNumberMatchStrategyImpl::IsSimStore( const MVPbkContactStore& aStore )
       
  1126     {
       
  1127     TVPbkContactStoreUriPtr uriPtr = aStore.StoreProperties().Uri();
       
  1128     if ( !uriPtr.UriDes().Compare( KVPbkSimGlobalAdnURI )
       
  1129             || !uriPtr.UriDes().Compare( KVPbkSimGlobalFdnURI )
       
  1130             || !uriPtr.UriDes().Compare( KVPbkSimGlobalSdnURI )
       
  1131             || !uriPtr.UriDes().Compare( KVPbkSimGlobalOwnNumberURI ) )
       
  1132         {
       
  1133         return ETrue;
       
  1134         }
       
  1135     return EFalse;
       
  1136     }
       
  1137 
       
  1138 void CVPbkPhoneNumberMatchStrategyImpl::LoadNumberParserPluginL()
       
  1139     {    
       
  1140     RImplInfoPtrArray   implInfoArray;
       
  1141     CleanupResetAndDestroyPushL( implInfoArray );
       
  1142     REComSession::ListImplementationsL( KUidEcomCntPhoneNumberParserInterface, 
       
  1143                                         implInfoArray );
       
  1144     // Load the first implementation found for KUidEcomCntPhoneNumberParserInterface 
       
  1145     const TInt count = implInfoArray.Count();
       
  1146     __ASSERT_ALWAYS( count > 0, User::Leave( KErrNotFound ) );
       
  1147     const TUid firstImplementationFound = implInfoArray[0]->ImplementationUid();
       
  1148     iParser = reinterpret_cast<CContactPhoneNumberParser*> 
       
  1149         ( CContactEcomPhoneNumberParser::NewL( firstImplementationFound ) );
       
  1150     CleanupStack::PopAndDestroy( &implInfoArray );
       
  1151     }
       
  1152 
       
  1153 CVPbkPhoneNumberMatchStrategy::CVPbkPhoneNumberMatchStrategy()
       
  1154     {
       
  1155     }
       
  1156 
       
  1157 EXPORT_C CVPbkPhoneNumberMatchStrategy* CVPbkPhoneNumberMatchStrategy::NewL(
       
  1158         const TConfig& aConfig,
       
  1159         CVPbkContactManager& aContactManager,
       
  1160         MVPbkContactFindObserver& aObserver)
       
  1161     {
       
  1162     if (aConfig.iMatchMode == EVPbkSequentialMatch)
       
  1163         {
       
  1164         return CVPbkPhoneNumberSequentialMatchStrategy::NewL(aConfig, aContactManager, aObserver);
       
  1165         }
       
  1166     else
       
  1167         {
       
  1168         return CVPbkPhoneNumberParallelMatchStrategy::NewL(aConfig, aContactManager, aObserver);
       
  1169         }
       
  1170    }
       
  1171 
       
  1172 CVPbkPhoneNumberMatchStrategy::~CVPbkPhoneNumberMatchStrategy()
       
  1173     {
       
  1174     delete iImpl;
       
  1175     }
       
  1176 
       
  1177 EXPORT_C void CVPbkPhoneNumberMatchStrategy::MatchL(const TDesC& aPhoneNumber)
       
  1178     {
       
  1179     InitMatchingL();
       
  1180 
       
  1181     iImpl->MatchL(aPhoneNumber);
       
  1182     }
       
  1183 
       
  1184 void CVPbkPhoneNumberMatchStrategy::BaseConstructL(
       
  1185         const TConfig& aConfig,
       
  1186         CVPbkContactManager& aContactManager,
       
  1187         MVPbkContactFindObserver& aObserver)
       
  1188     {
       
  1189     iImpl = CVPbkPhoneNumberMatchStrategyImpl::NewL(
       
  1190             *this, aConfig, aContactManager, aObserver);
       
  1191     }
       
  1192 
       
  1193 MVPbkContactFindObserver& CVPbkPhoneNumberMatchStrategy::FindObserver() const
       
  1194     {
       
  1195     return *iImpl;
       
  1196     }
       
  1197 
       
  1198 TInt CVPbkPhoneNumberMatchStrategy::MaxMatchDigits() const
       
  1199     {
       
  1200     return iImpl->MaxMatchDigits();
       
  1201     }
       
  1202 
       
  1203 TArray<MVPbkContactStore*> CVPbkPhoneNumberMatchStrategy::StoresToMatch() const
       
  1204     {
       
  1205     return iImpl->StoresToMatch();
       
  1206     }
       
  1207 
       
  1208 TBool CVPbkPhoneNumberMatchStrategy::IsSimStore( const MVPbkContactStore& aStore )
       
  1209     {
       
  1210     return iImpl->IsSimStore( aStore );
       
  1211     }
       
  1212 // End of File