predictivesearch/PcsAlgorithm/Algorithm1/src/CPcsAlgorithm1Utils.cpp
branchRCL_3
changeset 20 f4a778e096c2
child 21 9da50d567e3c
equal deleted inserted replaced
19:5b6f26637ad3 20:f4a778e096c2
       
     1 /*
       
     2 * Copyright (c) 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:  Supports initial search feature. 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDES
       
    20 #include "CPcsAlgorithm1Utils.h"
       
    21 #include "CPsData.h"
       
    22 #include "CPcsDefs.h"
       
    23 #include "CPcsCache.h"
       
    24 #include "CPsQuery.h"
       
    25 #include "CPsQueryItem.h"
       
    26 
       
    27 #include <collate.h>
       
    28 
       
    29 // CONSTANTS
       
    30 _LIT(KSpace, ' ');
       
    31 
       
    32 // Search contacts in a group URI template
       
    33 _LIT(KGroupIdUri, "cntdb://c:contacts.gdb?id="); 
       
    34 
       
    35 // ============================== MEMBER FUNCTIONS ============================
       
    36 
       
    37 // ----------------------------------------------------------------------------
       
    38 // CPcsAlgorithm1Utils::FormCompleteSearchResultsL()
       
    39 // Merges all the respective data store result sets to single set in sorted order.
       
    40 // ----------------------------------------------------------------------------
       
    41 void CPcsAlgorithm1Utils::FormCompleteSearchResultsL(RPointerArray<CPSDATA_R_PTR_ARRAY>& aSearchResultsArr, 
       
    42 												     RPointerArray<CPsData>& aSearchResults)
       
    43 {
       
    44     CleanupClosePushL( aSearchResults );
       
    45 	TInt maxIndex = 0;
       
    46     TInt maxValue = aSearchResultsArr[maxIndex]->Count();
       
    47     TLinearOrder<CPsData> rule( CPcsAlgorithm1Utils::CompareDataBySortOrderL );
       
    48     
       
    49     // Find the largest array in aSearchResultsArr
       
    50     for(TInt i = 1; i < aSearchResultsArr.Count(); i++)
       
    51     {
       
    52 		if(aSearchResultsArr[i]->Count() > maxValue)
       
    53 		{
       
    54 			maxIndex = i;
       
    55 			maxValue =aSearchResultsArr[i]->Count();
       
    56 		}    
       
    57     }
       
    58     
       
    59     // Assign the largets array to searchresults 
       
    60     for(TInt i = 0; i < aSearchResultsArr[maxIndex]->Count(); i++)
       
    61     {
       
    62     	aSearchResults.Append((*(aSearchResultsArr[maxIndex]))[i]);
       
    63     }
       
    64     
       
    65     // Merge the remaining result arrays to the largest array in sequential order
       
    66     for(TInt i = 0; i < aSearchResultsArr.Count(); i++)
       
    67     {
       
    68         // Check if we are not copying again the largest array
       
    69     	if(( i != maxIndex) && ((aSearchResultsArr[i])->Count() != 0))
       
    70     	{
       
    71     		TInt numElements = (aSearchResultsArr[i])->Count();
       
    72     		for( TInt j = 0; j < numElements; j++)
       
    73     		{
       
    74     			aSearchResults.InsertInOrderAllowRepeatsL((*(aSearchResultsArr[i]))[j], rule);
       
    75     		}
       
    76     	}
       
    77     }
       
    78     CleanupStack::Pop();
       
    79 }
       
    80 
       
    81 // ----------------------------------------------------------------------------
       
    82 // CPcsAlgorithm1Utils::CompareByCharacter()
       
    83 // Compare by character.
       
    84 // ----------------------------------------------------------------------------
       
    85 TInt CPcsAlgorithm1Utils::CompareByCharacter( const TChar& aFirst, const TChar& aSecond )
       
    86 {
       
    87     TInt retValue;
       
    88     if ( aFirst == aSecond )
       
    89         {
       
    90         retValue = 0;
       
    91         }
       
    92     else if ( aFirst < aSecond )
       
    93         {
       
    94         retValue = -1;
       
    95         }
       
    96     else 
       
    97         {
       
    98         retValue = 1;
       
    99         }
       
   100 
       
   101     return retValue;
       
   102 }
       
   103 
       
   104 // ----------------------------------------------------------------------------
       
   105 // CPcsAlgorithm1Utils::CompareByLength()
       
   106 // Compare by length.
       
   107 // ----------------------------------------------------------------------------
       
   108 TInt CPcsAlgorithm1Utils::CompareByLength( const HBufC& aFirst, const HBufC& aSecond )
       
   109 {
       
   110     return ( aFirst.Length() - aSecond.Length() );
       
   111 }
       
   112 
       
   113 // ----------------------------------------------------------------------------
       
   114 // CPcsAlgorithm1Utils::CompareExact()
       
   115 // Compare strings exactly case sensitively.
       
   116 // ----------------------------------------------------------------------------
       
   117 TBool CPcsAlgorithm1Utils::CompareExact( const TDesC& aFirst, const TDesC& aSecond )
       
   118 {
       
   119     return aFirst == aSecond;
       
   120 }
       
   121 
       
   122 // ----------------------------------------------------------------------------
       
   123 // CPcsAlgorithm1Utils::CompareCollate()
       
   124 // Compare strings with collate rules depending on locale.
       
   125 // ----------------------------------------------------------------------------
       
   126 TInt CPcsAlgorithm1Utils::CompareCollate( const TDesC& aFirst, const TDesC& aSecond )
       
   127 {
       
   128     return CPcsAlgorithm1Utils::MyCompareC(aFirst, aSecond);
       
   129 }
       
   130 
       
   131 // ----------------------------------------------------------------------------
       
   132 // CPcsAlgorithm1Utils::MyCompareKeyAndString()
       
   133 // Compare for keys and strings:
       
   134 // - Case sensitive compare for keys,
       
   135 // - Case insensitive and language dependent compare for Contact Data and Query.
       
   136 // ----------------------------------------------------------------------------
       
   137 TBool CPcsAlgorithm1Utils::MyCompareKeyAndString(const TDesC& aContactString,
       
   138                                                  const TDesC& aQueryAsString,
       
   139                                                  CPsQuery& aPsQuery)
       
   140 {
       
   141     TBool comparison = MyCompareK(aContactString, aQueryAsString, aPsQuery); 
       
   142         
       
   143     if (comparison)
       
   144         {
       
   145         // The aContactString can be longer than aQueryAsString and we want a match to be
       
   146         // successful if both strings are equal for the length of the query (aQueryAsString)
       
   147         comparison = (MyCompareC(aContactString.Left(aQueryAsString.Length()), aQueryAsString) == 0);
       
   148         }
       
   149     
       
   150     return comparison;
       
   151 }
       
   152 
       
   153 // ----------------------------------------------------------------------------
       
   154 // CPcsAlgorithm1Utils::MyCompareK()
       
   155 // Case sensitive compare for keys of first 2 input params.
       
   156 // INFO: We have some cases that TPtiKey "Z" (uppercase) is mapping chars "Zz...."
       
   157 //       and TPtiKey "z" (lowercase) is mapping chars ".," or "Ää".
       
   158 //       The comparison of "Z" and "z" should fail for the keys.
       
   159 // ----------------------------------------------------------------------------
       
   160 TBool CPcsAlgorithm1Utils::MyCompareK(const TDesC& aLeft, const TDesC& aRight, CPsQuery& aPsQuery)
       
   161 {
       
   162     TBool comparison = ETrue;
       
   163 
       
   164     if ( (aLeft.Length() < aPsQuery.Count()) || (aRight.Length() < aPsQuery.Count()) )
       
   165         {
       
   166         comparison = EFalse;
       
   167         }
       
   168     else
       
   169         {
       
   170         for ( TInt i = 0; i < aPsQuery.Count(); i++ )
       
   171             {
       
   172             CPsQueryItem* currentItemPtr;
       
   173             TRAPD ( err, currentItemPtr = &(aPsQuery.GetItemAtL(i)) );
       
   174             if ( err != KErrNone
       
   175                  || ( CPcsKeyMap::IsModePredictive(currentItemPtr->Mode())
       
   176                     && aLeft[i] != aRight[i] ) )
       
   177                 {
       
   178                 comparison = EFalse;
       
   179                 break;
       
   180                 }
       
   181             }
       
   182         }
       
   183 
       
   184     return comparison;
       
   185 }
       
   186 
       
   187 // ----------------------------------------------------------------------------
       
   188 // CPcsAlgorithm1Utils::MyCompareC()
       
   189 // Lang specific MyCompareC
       
   190 // ----------------------------------------------------------------------------
       
   191 TInt CPcsAlgorithm1Utils::MyCompareC(const TDesC& aLeft, const TDesC& aRight)
       
   192 {
       
   193     // Get the current language
       
   194     TLanguage lang = User::Language();
       
   195         
       
   196 	// Get the standard method
       
   197 	TCollationMethod meth = *Mem::CollationMethodByIndex( 0 );
       
   198 	meth.iFlags |= TCollationMethod::EIgnoreNone;
       
   199 	meth.iFlags |= TCollationMethod::EFoldCase;
       
   200     
       
   201     if ( lang == ELangHindi || lang == ELangMarathi )
       
   202     {
       
   203     	meth.iFlags |= TCollationMethod::EIgnoreCombining;    	
       
   204     }
       
   205    
       
   206 	// Collation level 0 is used
       
   207 	TInt comparison(aLeft.CompareC( aRight, 0, &meth ));
       
   208 	return comparison;
       
   209 }
       
   210 
       
   211 // ----------------------------------------------------------------------------
       
   212 // CPcsAlgorithm1Utils::CompareDataBySortOrderL()
       
   213 // TLinearOrder rule for comparison of data objects
       
   214 // ----------------------------------------------------------------------------
       
   215 TInt CPcsAlgorithm1Utils::CompareDataBySortOrderL(const CPsData& aObject1, 
       
   216                                                   const CPsData& aObject2)
       
   217     {
       
   218     TInt compareRes(0);
       
   219     
       
   220     if( CPsData::CompareById(aObject1, aObject2) )
       
   221         {
       
   222         return compareRes;
       
   223         }
       
   224     
       
   225     // Fetch the cache list stored in TLS to recover the sort order
       
   226     typedef RPointerArray<CPcsCache> PTR;
       
   227     PTR* pcsCache = static_cast<PTR*>(Dll::Tls());
       
   228     User::LeaveIfNull(pcsCache);
       
   229     
       
   230 	CPcsCache* cache1 = (*pcsCache)[aObject1.UriId()];
       
   231     CPcsCache* cache2 = (*pcsCache)[aObject2.UriId()];
       
   232 	RArray<TInt> indexOrder1;
       
   233     RArray<TInt> indexOrder2;
       
   234 	  
       
   235     // Get the index order based on sort order from the cache
       
   236 	cache1->GetIndexOrder(indexOrder1);
       
   237 	CleanupClosePushL(indexOrder1);
       
   238 	cache2->GetIndexOrder(indexOrder2);
       
   239 	CleanupClosePushL(indexOrder2);
       
   240 
       
   241 	TInt idx2 = 0;
       
   242 	for(TInt idx1 = 0; 
       
   243         idx1 < indexOrder1.Count() && idx2 < indexOrder2.Count() && compareRes == 0; 
       
   244         idx1++)
       
   245         {
       
   246         TInt object1Idx = indexOrder1[idx1];
       
   247         HBufC* strCompare1 = aObject1.Data(object1Idx)->Des().AllocLC();
       
   248         
       
   249         if ( object1Idx < aObject1.DataElementCount() 
       
   250              && aObject1.Data(object1Idx)
       
   251              && strCompare1->Length() )
       
   252             {
       
   253             strCompare1->Des().TrimAll();
       
   254             
       
   255             for(; idx2 < indexOrder2.Count(); idx2++)
       
   256                 {
       
   257                 TInt object2Idx = indexOrder2[idx2];
       
   258                 
       
   259                 HBufC* strCompare2 = aObject2.Data(object2Idx)->Des().AllocLC();
       
   260                 
       
   261                 if( strCompare2->Length() )
       
   262                     {
       
   263                     strCompare2->Des().TrimAll();
       
   264                     
       
   265                     compareRes = CPcsAlgorithm1Utils::MyCompareC(*strCompare1, *strCompare2);
       
   266                     
       
   267                     CleanupStack::PopAndDestroy(strCompare2);
       
   268                     
       
   269                     if( compareRes == 0 )
       
   270                         {
       
   271                         idx2++;
       
   272                         }
       
   273                     break;
       
   274                     }
       
   275                 CleanupStack::PopAndDestroy(strCompare2);
       
   276                 }
       
   277             }
       
   278         CleanupStack::PopAndDestroy(strCompare1);
       
   279         }
       
   280   
       
   281 	CleanupStack::PopAndDestroy(&indexOrder2);
       
   282     CleanupStack::PopAndDestroy(&indexOrder1);
       
   283 
       
   284     return compareRes;
       
   285     }
       
   286 
       
   287 
       
   288 // ----------------------------------------------------------------------------
       
   289 // CPcsAlgorithm1Utils::MyTrim()
       
   290 // Trim off all white spaces and special characters
       
   291 // This behavior is required to mimic the current phonebook sort sequence
       
   292 // ----------------------------------------------------------------------------
       
   293 void CPcsAlgorithm1Utils::MyTrim(TDes& aString)
       
   294 {           
       
   295     for ( TInt i = aString.Length(); --i >= 0; )
       
   296     {
       
   297         TChar c = (TChar) aString[i];
       
   298         
       
   299         if ( ! c.IsAlphaDigit() )
       
   300         {
       
   301             aString.Replace( i, 1, KSpace );
       
   302         }
       
   303     }
       
   304     
       
   305     aString.TrimAll();
       
   306 }
       
   307 
       
   308 // ----------------------------------------------------------------------------
       
   309 // CPcsAlgorithm1Utils::IsGroupUri()
       
   310 // Check if the input URI is of contact search in a group template form
       
   311 // ----------------------------------------------------------------------------
       
   312 TBool CPcsAlgorithm1Utils::IsGroupUri(TDesC& aURI)
       
   313 {
       
   314     TBuf<255> uri(aURI);
       
   315     uri.LowerCase();
       
   316     
       
   317     TInt index = uri.FindF(KGroupIdUri);
       
   318     
       
   319     if ( index == KErrNotFound )
       
   320     {
       
   321         return EFalse;
       
   322     }
       
   323     
       
   324     return ETrue;
       
   325 }
       
   326 
       
   327 // ----------------------------------------------------------------------------
       
   328 // CPcsAlgorithm1Helper::FilterDataFieldsL()
       
   329 // Constructs a bit pattern using the required/supported data fields
       
   330 // For example, 6, 4 and 27 are supported fields <-- 00000111
       
   331 //              6 and 4 are required fields      <-- 00000011
       
   332 // Bit pattern returned is 00000011.
       
   333 // ----------------------------------------------------------------------------
       
   334 TUint8 CPcsAlgorithm1Utils::FilterDataFieldsL(const RArray<TInt>& aRequiredDataFields,
       
   335                                               const RArray<TInt>& aSupportedDataFields)
       
   336 {
       
   337     TUint8 filteredMatch = 0x0;
       
   338 
       
   339     for ( TInt i = 0; i < aSupportedDataFields.Count(); i++ )
       
   340     {
       
   341         for ( TInt j = 0; j < aRequiredDataFields.Count(); j++ )
       
   342         {
       
   343             if ( aSupportedDataFields[i] == aRequiredDataFields[j] )
       
   344             {
       
   345                 TUint8 val = 1 << i;
       
   346                 filteredMatch |= val;
       
   347             }
       
   348         }
       
   349     }
       
   350 
       
   351     return filteredMatch;
       
   352 }
       
   353 
       
   354 // ----------------------------------------------------------------------------
       
   355 // CPcsAlgorithm1Utils::AppendMatchToSeqL
       
   356 // ----------------------------------------------------------------------------
       
   357 void CPcsAlgorithm1Utils::AppendMatchToSeqL( 
       
   358         RPointerArray<TDesC>& aMatchSeq, const TDesC& aMatch )
       
   359     {
       
   360     CleanupResetAndDestroyPushL( aMatchSeq );
       
   361     
       
   362     HBufC* seq = aMatch.AllocLC();
       
   363     seq->Des().UpperCase();
       
   364     TIdentityRelation<TDesC> rule(CompareExact);
       
   365     if ( aMatchSeq.Find(seq, rule) == KErrNotFound )
       
   366         {
       
   367         aMatchSeq.AppendL(seq);
       
   368         CleanupStack::Pop( seq );
       
   369         }
       
   370     else 
       
   371         {
       
   372         CleanupStack::PopAndDestroy( seq );
       
   373         }
       
   374     CleanupStack::Pop( &aMatchSeq );
       
   375     }
       
   376 
       
   377 // End of File
       
   378