phonebookengines/VirtualPhonebook/VPbkEng/src/CVPbkPhoneNumberMatchStrategy.cpp
branchRCL_3
changeset 35 4ae315f230bc
parent 0 e686773b3f54
child 45 34879f5cfc63
--- a/phonebookengines/VirtualPhonebook/VPbkEng/src/CVPbkPhoneNumberMatchStrategy.cpp	Tue May 11 16:00:21 2010 +0300
+++ b/phonebookengines/VirtualPhonebook/VPbkEng/src/CVPbkPhoneNumberMatchStrategy.cpp	Tue May 25 12:26:45 2010 +0300
@@ -78,7 +78,11 @@
         void VPbkSingleContactOperationFailed(
                 MVPbkContactOperationBase& aOperation,
                 TInt aError);
-
+   
+    private:
+        /// Phone number types
+        enum TNumberType { ENotInitialized, EUnknown, EDigit, EPlus, EOneZero, ETwoZeros };
+        
     private: // Implementation
         CVPbkPhoneNumberMatchStrategyImpl(CVPbkPhoneNumberMatchStrategy& aParent);
         void ConstructL(
@@ -124,6 +128,11 @@
          */
         TPtrC NameFieldValueL( MVPbkStoreContact* aContact, TVPbkFieldTypeName aFieldType );
         
+        TBool ValidateBestMatchingRulesL( const TDesC& aNumber );
+        TBool CheckBestMatchingRules( const TDesC& aNumberA, TNumberType aNumberAType,
+                const TDesC& aNumberB, TNumberType aNumberBType  );
+        TInt FormatAndCheckNumberType( TDes& aNumber );
+        
     private: // Data
         CVPbkPhoneNumberMatchStrategy& iParent;
         /// Ref: The contact manager instance to be used for searching.
@@ -170,6 +179,8 @@
         RPointerArray <HBufC> iTempNameTokensArray;
         /// Indicates if all contact in iResult are the same
         TBool iDoubledContacts;
+        /// type of iPhoneNumber
+        TNumberType iPhoneNumberType;
     };
 
 CVPbkPhoneNumberMatchStrategyImpl::CVPbkPhoneNumberMatchStrategyImpl(
@@ -226,7 +237,7 @@
 	    iLastNameSelector = CVPbkFieldTypeSelector::NewL( resReader, iContactManager->FieldTypes() );
 	    CleanupStack::PopAndDestroy( lastNameSelectorBuf );
     	}
-    
+
     CleanupStack::PopAndDestroy( &resFile );
     }
 
@@ -267,6 +278,7 @@
     HBufC* phoneNumber = aPhoneNumber.AllocL();
     delete iPhoneNumber;
     iPhoneNumber = phoneNumber;
+    iPhoneNumberType = ENotInitialized;
     
     if ( iWorkingResults )
         {
@@ -351,17 +363,19 @@
                 {
                 iResults = CVPbkContactLinkArray::NewL();
                 }
-            if ( iDoubledContacts )
-                {
-                iDoubledContacts = CheckContactDuplicationL( iStoreContact );
-                }
             
             MVPbkContactLink* result = IsValidResultLC( iStoreContact );
             if ( result )
                 {
                 iResults->AppendL( result );
                 CleanupStack::Pop(); // MVPbkContactLink
+                
+                if ( iDoubledContacts )
+                    {
+                    iDoubledContacts = CheckContactDuplicationL( iStoreContact );
+                    }
                 }
+
             delete iStoreContact;
             iStoreContact = NULL;
                 
@@ -509,7 +523,8 @@
     {
     MVPbkContactLink* result = NULL;
 
-    if (!(iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkExactMatchFlag))
+    if (!(iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkExactMatchFlag)
+            && !(iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkBestMatchingFlag))
         {
         // If exact match is not needed we will accept the contact as valid
         // if it is not NULL
@@ -539,10 +554,19 @@
             if (data.DataType() == EVPbkFieldStorageTypeText)
                 {
                 const TDesC& dataText = MVPbkContactFieldTextData::Cast(data).Text();
-                TPtrC dataTextPtr = dataText.Right(Min(dataText.Length(), iMaxMatchDigits));
-                if (dataTextPtr == matchedNumber)
+                if (iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkExactMatchFlag)
                     {
-                    result = iFieldFilter->FieldAt(i).CreateLinkLC();
+                    TPtrC dataTextPtr = dataText.Right(Min(dataText.Length(), iMaxMatchDigits));
+                    if (dataTextPtr == matchedNumber)
+                        {
+                        result = iFieldFilter->FieldAt(i).CreateLinkLC();
+                        break;
+                        }
+                    }
+                else if (iMatchFlags & CVPbkPhoneNumberMatchStrategy::EVPbkBestMatchingFlag
+                            && ValidateBestMatchingRulesL(dataText))
+                    {
+                    result = aContact->CreateLinkLC();
                     break;
                     }
                 }
@@ -695,6 +719,232 @@
         }
     }
 
+// Removes non-digit chars except plus form the beginning
+// Checks if number matches to one of defined types
+//
+TInt CVPbkPhoneNumberMatchStrategyImpl::FormatAndCheckNumberType( TDes& aNumber )
+    {
+    _LIT( KOneZeroPattern, "0*" );
+    _LIT( KTwoZerosPattern, "00*" );
+    _LIT( KPlusPattern, "+*" );
+    const TChar KPlus = TChar('+');
+    const TChar KZero = TChar('0');
+    const TChar KAsterisk = TChar('*');
+    const TChar KHash = TChar('#');
+    
+    for( TInt pos = 0; pos < aNumber.Length(); ++pos )
+        {
+        TChar chr = aNumber[pos];
+        if ( !chr.IsDigit() && !( pos == 0 && chr == KPlus  )
+                && !( chr == KAsterisk ) && !( chr == KHash ) )
+            {
+            aNumber.Delete( pos, 1 );
+            --pos;
+            }
+        }
+    
+	TInt format;
+	
+    if ( !aNumber.Match( KTwoZerosPattern ) && aNumber.Length() > 2 && aNumber[2] != KZero )
+        {
+        format = ETwoZeros;
+        }
+    else if ( !aNumber.Match( KOneZeroPattern )&& aNumber.Length() > 1 && aNumber[1] != KZero )
+        {
+        format = EOneZero;
+        }
+    else if ( !aNumber.Match( KPlusPattern ) && aNumber.Length() > 1 && aNumber[1] != KZero )
+        {
+        format = EPlus;
+        }
+    else if ( aNumber.Length() > 0 && aNumber[0] != KZero && ( ( TChar ) aNumber[0] ).IsDigit() )
+        {
+        format = EDigit;
+        }
+	else
+		{
+        format = EUnknown;
+	    }
+
+    return format;
+    }
+
+TBool CVPbkPhoneNumberMatchStrategyImpl::ValidateBestMatchingRulesL( const TDesC& aNumber )
+    {
+    if ( iPhoneNumberType == ENotInitialized )
+        {
+        TPtr16 phoneNumber = iPhoneNumber->Des();
+        iPhoneNumberType = ( TNumberType ) FormatAndCheckNumberType( phoneNumber );
+        }
+    
+    HBufC* number = aNumber.AllocLC();
+    TPtr16 phoneNumber = number->Des();
+    TNumberType numberType = ( TNumberType ) FormatAndCheckNumberType( phoneNumber );
+
+    TBool match = ( !phoneNumber.Compare( *iPhoneNumber ) ||
+                  CheckBestMatchingRules( *iPhoneNumber, iPhoneNumberType, *number, numberType  ) ||
+                  CheckBestMatchingRules( *number, numberType, *iPhoneNumber, iPhoneNumberType  ) );
+
+    CleanupStack::PopAndDestroy( number );
+
+    return match;
+    }
+
+TBool CVPbkPhoneNumberMatchStrategyImpl::CheckBestMatchingRules(
+        const TDesC& aNumberA, TNumberType aNumberAType,
+        const TDesC& aNumberB, TNumberType aNumberBType  )
+    {
+    TBool result = EFalse;
+    
+    // Rules for matching not identical numbers
+    // Rules details are presented in Best_Number_Matching_Algorithm_Description.doc
+    
+    // rule International-International 1
+    if ( !result && aNumberAType == EPlus && aNumberBType == ETwoZeros )
+        {
+        TPtrC numberA = aNumberA.Right( aNumberA.Length() - 1 );
+        TPtrC numberB = aNumberB.Right( aNumberB.Length() - 2 );
+        result = !( numberA.Compare( numberB ) );
+        if ( result )
+            {
+            return result;
+            }
+        }
+
+    // rule International-International 2
+    if ( aNumberAType == EPlus && aNumberBType == EDigit )
+        {
+        TPtrC numberA = aNumberA.Right( aNumberA.Length() - 1 );
+        if ( numberA.Length() < aNumberB.Length() )
+            {
+            TPtrC numberB = aNumberB.Right( numberA.Length() );
+            result = !( numberA.Compare( numberB ) );
+            if ( result )
+                {
+                return result;
+                }
+            }
+        }
+
+    // rule International-International 3
+    if ( aNumberAType == ETwoZeros && aNumberBType == EDigit )
+        {
+        TPtrC numberA = aNumberA.Right( aNumberA.Length() - 2 );
+        if ( numberA.Length() < aNumberB.Length() )
+            {
+            TPtrC numberB = aNumberB.Right( numberA.Length() );
+            result = !( numberA.Compare( numberB ) );
+            if ( result )
+                {
+                return result;
+                }
+            }
+        }
+
+    // rule International-Operator 1
+    if ( aNumberAType == EOneZero && aNumberBType == EPlus
+            || aNumberAType == EDigit && aNumberBType == EPlus )
+        {
+        TPtrC numberA;
+        if ( aNumberAType == EOneZero )
+            {
+            numberA.Set( aNumberA.Right( aNumberA.Length() - 1 ) );
+            }
+        else
+            {
+            numberA.Set( aNumberA );
+            }
+        if ( numberA.Length() < aNumberB.Length() - 1 )
+            {
+            TPtrC numberB = aNumberB.Right( numberA.Length() );
+            result = !( numberA.Compare( numberB ) );
+            if ( result )
+                {
+                return result;
+                }
+            }
+        }
+
+    // rule International-Operator 2
+    if ( aNumberAType == EOneZero && aNumberBType == ETwoZeros
+            || aNumberAType == EDigit && aNumberBType == ETwoZeros )
+        {
+        TPtrC numberA;
+        if ( aNumberAType == EOneZero )
+            {
+            numberA.Set( aNumberA.Right( aNumberA.Length() - 1 ) );
+            }
+        else
+            {
+            numberA.Set( aNumberA );
+            }
+        if ( numberA.Length() < aNumberB.Length() - 2 )
+            {
+            TPtrC numberB = aNumberB.Right( numberA.Length() );
+            result = !( numberA.Compare( numberB ) );
+            if ( result )
+                {
+                return result;
+                }
+            }
+        }
+
+    // rule International-Operator 3
+    if ( aNumberAType == EOneZero && aNumberBType == EDigit
+            || aNumberAType == EDigit && aNumberBType == EDigit )
+        {
+        TPtrC numberA;
+        if ( aNumberAType == EOneZero )
+            {
+            numberA.Set( aNumberA.Right( aNumberA.Length() - 1 ) );
+            }
+        else
+            {
+            numberA.Set( aNumberA );
+            }
+        if ( numberA.Length() < aNumberB.Length() )
+            {
+            TPtrC numberB = aNumberB.Right( numberA.Length() );
+            result = !( numberA.Compare( numberB ) );
+            if ( result )
+                {
+                return result;
+                }
+            }
+        }
+
+    // rule Operator-Operator 1
+    if ( aNumberAType == EOneZero && aNumberBType == EDigit )
+        {
+        TPtrC numberA = aNumberA.Right( aNumberA.Length() - 1 );
+        result = !( numberA.Compare( aNumberB ) );
+            {
+            if ( result )
+                {
+                return result;
+                }
+            }
+        }
+    
+    // rule North America Numbering Plan 1
+    if ( aNumberAType == EDigit && aNumberBType == EPlus )
+        {
+        TPtrC numberB = aNumberB.Right( aNumberB.Length() - 1 );
+        result = !( aNumberA.Compare( numberB ) );
+            {
+            if ( result )
+                {
+                return result;
+                }
+            }
+        }
+
+    // More exceptional acceptance rules can be added here
+	// Keep rules updated in the document Best_Number_Matching_Algorithm_Description.doc
+
+    return result;
+    }
+
 CVPbkPhoneNumberMatchStrategy::CVPbkPhoneNumberMatchStrategy()
     {
     }