predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsAlgorithm2Helper.cpp
branchRCL_3
changeset 18 d4f567ce2e7c
parent 7 b3431bff8c19
equal deleted inserted replaced
17:2666d9724c76 18:d4f567ce2e7c
    14 * Description: Predictive Contact Search Algorithm 1 helper class
    14 * Description: Predictive Contact Search Algorithm 1 helper class
    15 *
    15 *
    16 */
    16 */
    17 
    17 
    18 // INCLUDES
    18 // INCLUDES
    19 #include <FindUtil.h>
    19 #include <PbkGlobalSettingFactory.h>
    20 #include "FindUtilChineseECE.h"
    20 #include "FindUtilChineseECE.h"
    21 #include "CPcsAlgorithm2.h"
    21 #include "CPcsAlgorithm2.h"
    22 #include "CPcsAlgorithm2Helper.h"
    22 #include "CPcsAlgorithm2Helper.h"
    23 #include "CPcsAlgorithm2Utils.h"
    23 #include "CPcsAlgorithm2Utils.h"
    24 #include "CPcsDebug.h"
    24 #include "CPcsDebug.h"
    25 #include "CPcsCache.h"
    25 #include "CPcsCache.h"
    26 #include "CPcsKeyMap.h"
    26 #include "CPcsKeyMap.h"
    27 #include "CPsData.h"
    27 #include "CPsData.h"
    28 #include "CWords.h"
       
    29 #include "CPsQuery.h"
    28 #include "CPsQuery.h"
    30 #include "CPsQueryItem.h"
    29 #include "CPsQueryItem.h"
    31 #include "CPsDataPluginInterface.h"
    30 #include "CPsDataPluginInterface.h"
    32 #include "CPcsPoolElement.h"
    31 #include "CPcsPoolElement.h"
    33 
    32 
    34 // Compare functions
       
    35 TBool Compare1(const TDesC& aFirst, const TDesC& aSecond)
       
    36     {
       
    37     return aFirst == aSecond;
       
    38     }
       
    39 
       
    40 TBool Compare2(const TDesC& aFirst, const TDesC& aSecond)
       
    41     {
       
    42     return CPcsAlgorithm2Utils::MyCompareC(aFirst, aSecond);
       
    43     }
       
    44 
    33 
    45 // ============================== MEMBER FUNCTIONS ============================
    34 // ============================== MEMBER FUNCTIONS ============================
    46 
    35 
    47 // ----------------------------------------------------------------------------
    36 // ----------------------------------------------------------------------------
    48 // CPcsAlgorithm2Helper::NewL
    37 // CPcsAlgorithm2Helper::NewL
    68 // ----------------------------------------------------------------------------
    57 // ----------------------------------------------------------------------------
    69 CPcsAlgorithm2Helper::CPcsAlgorithm2Helper()
    58 CPcsAlgorithm2Helper::CPcsAlgorithm2Helper()
    70     {
    59     {
    71     PRINT ( _L("Enter CPcsAlgorithm2Helper::CPcsAlgorithm2") );
    60     PRINT ( _L("Enter CPcsAlgorithm2Helper::CPcsAlgorithm2") );
    72     PRINT ( _L("End CPcsAlgorithm2Helper::CPcsAlgorithm2") );
    61     PRINT ( _L("End CPcsAlgorithm2Helper::CPcsAlgorithm2") );
       
    62     iMaxCount = 0;
    73     }
    63     }
    74 
    64 
    75 // ----------------------------------------------------------------------------
    65 // ----------------------------------------------------------------------------
    76 // CPcsAlgorithm2Helper::ConstructL
    66 // CPcsAlgorithm2Helper::ConstructL
    77 // Two Phase Construction
    67 // Two Phase Construction
    79 void CPcsAlgorithm2Helper::ConstructL(CPcsAlgorithm2* aAlgorithm)
    69 void CPcsAlgorithm2Helper::ConstructL(CPcsAlgorithm2* aAlgorithm)
    80     {
    70     {
    81     PRINT ( _L("Enter CPcsAlgorithm2Helper::ConstructL") );
    71     PRINT ( _L("Enter CPcsAlgorithm2Helper::ConstructL") );
    82 
    72 
    83     iAlgorithm = aAlgorithm;
    73     iAlgorithm = aAlgorithm;
    84     keyMap = iAlgorithm->GetKeyMap();
    74     iKeyMap = iAlgorithm->GetKeyMap();
    85 
    75 
       
    76     iPbkSettings = PbkGlobalSettingFactory::CreatePersistentSettingL();
       
    77     iPbkSettings->ConnectL( MPbkGlobalSetting::EGeneralSettingCategory );
       
    78     iPbkSettings->RegisterObserverL( this );
       
    79     UpdateNameOrderL();
       
    80     
    86     PRINT ( _L("End CPcsAlgorithm2Helper::ConstructL") );
    81     PRINT ( _L("End CPcsAlgorithm2Helper::ConstructL") );
    87     }
    82     }
    88 
    83 
    89 // ----------------------------------------------------------------------------
    84 // ----------------------------------------------------------------------------
    90 // CPcsAlgorithm2Helper::CPcsAlgorithm2Helper
    85 // CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper
    91 // Destructor
    86 // Destructor
    92 // ----------------------------------------------------------------------------
    87 // ----------------------------------------------------------------------------
    93 CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper()
    88 CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper()
    94     {
    89     {
    95     PRINT ( _L("Enter CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper") );
    90     PRINT ( _L("Enter CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper") );
    96     iSearchResultsArr.ResetAndDestroy();
    91     iSearchResultsArr.ResetAndDestroy();
    97     PRINT ( _L("End CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper") );
    92     PRINT ( _L("End CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper") );
    98     }
    93     }
    99 
    94 
   100 // ----------------------------------------------------------------------------
    95 // ----------------------------------------------------------------------------
   101 // CPcsAlgorithm2Helper::SearchMixedL
    96 // CPcsAlgorithm2Helper::SearchSingleL
   102 // Search function for input with both ITU-T and QWERTY mode
    97 // Search function for input with both ITU-T and QWERTY mode
   103 // ----------------------------------------------------------------------------
    98 // ----------------------------------------------------------------------------
   104 void CPcsAlgorithm2Helper::SearchMixedL(const CPsSettings& aSettings,
    99 void CPcsAlgorithm2Helper::SearchSingleL(const CPsSettings& aSettings,
   105                                         CPsQuery& aPsQuery, TBool isSearchInGroup,
   100                                          CPsQuery& aPsQuery, 
   106                                         RArray<TInt>& aContactsInGroup,
   101                                          TBool aIsSearchInGroup,
   107                                         RPointerArray<CPsData>& searchResults,
   102                                          const RArray<TInt>& aContactsInGroup,
   108                                         RPointerArray<CPsPattern>& searchSeqs)
   103                                          RPointerArray<CPsData>& aSearchResults,
   109     {
   104                                          RPointerArray<CPsPattern>& aSearchSeqs)
   110     __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchMixedL") );
   105     {
   111 
   106     PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchSingleL") );
   112     PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchMixedL") );
   107 
   113 
   108     //__LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchSingleL") );
       
   109 
       
   110     iMaxCount = aSettings.MaxResults();
       
   111     
   114     // Create filtering helper for the required sort type
   112     // Create filtering helper for the required sort type
   115     TSortType sortType = aSettings.GetSortType();
   113     TSortType sortType = aSettings.GetSortType();
   116     CPcsAlgorithm2FilterHelper* filterHelper =
   114     CPcsAlgorithm2FilterHelper* filterHelper =
   117             CPcsAlgorithm2FilterHelper::NewL(sortType);
   115             CPcsAlgorithm2FilterHelper::NewL(sortType);
       
   116     CleanupStack::PushL( filterHelper );
       
   117     
       
   118     // Search from cache based on first character
       
   119     const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0);
       
   120     TInt cachePoolId = iKeyMap->PoolIdForCharacter( firstCharItem.Character(), firstCharItem.Mode() );
   118 
   121 
   119     // Reset the result set array for new search
   122     // Reset the result set array for new search
   120     iSearchResultsArr.ResetAndDestroy();
   123     iSearchResultsArr.ResetAndDestroy();
   121 
   124 
   122     // Get the data stores
   125     // Get the data stores
   123     RPointerArray<TDesC> aDataStores;
   126     RPointerArray<TDesC> dataStores;
   124     aSettings.SearchUrisL(aDataStores);
   127     CleanupResetAndDestroyPushL( dataStores );
       
   128     aSettings.SearchUrisL(dataStores);
   125 
   129 
   126     // Get the required display fields from the client
   130     // Get the required display fields from the client
   127     RArray<TInt> requiredDataFields;
   131     RArray<TInt> requiredDataFields;
       
   132     CleanupClosePushL( requiredDataFields );
   128     aSettings.DisplayFieldsL(requiredDataFields);
   133     aSettings.DisplayFieldsL(requiredDataFields);
   129     
       
   130     // Search from cache based on first character
       
   131      const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0);
       
   132      TInt numValue  = keyMap->PoolIdForCharacter( firstCharItem.Character() );
       
   133 
   134 
   134     // Perform search for each required data store
   135     // Perform search for each required data store
   135     RPointerArray<CPcsPoolElement> elements;
   136     RPointerArray<CPcsPoolElement> elements;
   136 
   137     CleanupClosePushL( elements );
   137     for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++)
   138     const TInt dataStoresCount = dataStores.Count();
   138         {
   139 
   139 
   140     for (TInt dsIndex = 0; dsIndex < dataStoresCount; dsIndex++)
   140         RPointerArray<CPsData> *temp = new (ELeave) RPointerArray<CPsData> ();
   141         {
   141         iSearchResultsArr.Append(temp);
   142         RPointerArray<CPsData>* temp = new (ELeave) RPointerArray<CPsData> ();
       
   143         CleanupStack::PushL( temp );
       
   144         iSearchResultsArr.AppendL( temp );
       
   145         CleanupStack::Pop( temp );
   142 
   146 
   143         // Get the contents for this data store
   147         // Get the contents for this data store
   144         TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex]));
   148         TInt arrayIndex = iAlgorithm->GetCacheIndex(*(dataStores[dsIndex]));
   145         if (arrayIndex < 0)
   149         if (arrayIndex < 0)
   146             {
   150             {
   147             continue;
   151             continue;
   148             }
   152             }
   149         CPcsCache* cache = iAlgorithm->GetCache(arrayIndex);
   153         CPcsCache* cache = iAlgorithm->GetCache(arrayIndex);
   150         cache->GetContactsForKeyL(numValue, elements);
   154         cache->GetContactsForKeyL(cachePoolId, elements);
       
   155 
       
   156         // Get the supported data fields for this data store
       
   157         RArray<TInt> supportedDataFields;
       
   158         CleanupClosePushL( supportedDataFields );
       
   159         cache->GetDataFields(supportedDataFields);
       
   160 
       
   161         // Get the filtered data fields for this data store
       
   162         TUint8 filteredDataMatch = CPcsAlgorithm2Utils::FilterDataFieldsL(requiredDataFields,
       
   163                                                                           supportedDataFields);
   151 
   164 
   152         // Perform filtering
   165         // Perform filtering
   153         FilterResultsMixedL(filterHelper, elements, aPsQuery,
   166         FilterResultsSingleL(filterHelper,
   154                             isSearchInGroup, aContactsInGroup);
   167                              elements,
   155 
   168                              aPsQuery,
   156         // If alphabetical sorting, get the results for this datastore               
   169                              filteredDataMatch,
       
   170                              aIsSearchInGroup,
       
   171                              aContactsInGroup);
       
   172 
       
   173         // If alphabetical sorting, get the results for this datastore
   157         if (sortType == EAlphabetical)
   174         if (sortType == EAlphabetical)
   158             {
   175             {
   159             filterHelper->GetResults(*(iSearchResultsArr[dsIndex]));
   176             filterHelper->GetResults(*(iSearchResultsArr[dsIndex]));
   160             }
   177             }
   161 
   178 
   162         elements.Reset();
   179         elements.Reset();
   163         }
   180         CleanupStack::PopAndDestroy( &supportedDataFields ); // Close
   164 
   181         }
   165     aDataStores.ResetAndDestroy();
   182 
   166     requiredDataFields.Reset();
   183     CleanupStack::PopAndDestroy( &elements );           // Close
       
   184     CleanupStack::PopAndDestroy( &requiredDataFields ); // Close
       
   185     CleanupStack::PopAndDestroy( &dataStores );         // ResetAndDestroy
   167 
   186 
   168     // If alphabetical sorting, merge the result sets of all datastores
   187     // If alphabetical sorting, merge the result sets of all datastores
   169     if (sortType == EAlphabetical)
   188     if (sortType == EAlphabetical)
   170         {
   189         {
   171         // Form the complete searchResults array
   190         // Form the complete searchResults array
   172         CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iSearchResultsArr,
   191         CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iSearchResultsArr,
   173                                                         searchResults);
   192                                                         aSearchResults);
   174         }
   193         }
   175     else
   194     else
   176         {
   195         {
   177         // Results are already sorted pattern based
   196         // Results are already sorted pattern based
   178         filterHelper->GetResults(searchResults);
   197         filterHelper->GetResults(aSearchResults);
   179         }
   198         }
   180 
   199 
   181     // Get the sorted match sequence list
   200     // Get the sorted match sequence list
   182     filterHelper->GetPatternsL(searchSeqs);
   201     filterHelper->GetPatternsL(aSearchSeqs);
   183 
   202 
   184     PRINT1 ( _L("Number of search results = %d"), searchResults.Count() );
   203     PRINT1 ( _L("Number of search results = %d"), aSearchResults.Count() );
   185 
   204 
   186     // Cleanup         
   205     // Cleanup
   187     for (TInt i = 0; i < iSearchResultsArr.Count(); i++)
   206     const TInt searchResultsArrCount = iSearchResultsArr.Count();
       
   207     for (TInt i = 0; i < searchResultsArrCount; i++)
   188         {
   208         {
   189         iSearchResultsArr[i]->Reset();
   209         iSearchResultsArr[i]->Reset();
   190         delete iSearchResultsArr[i];
   210         }
   191         iSearchResultsArr[i] = NULL;
       
   192         }
       
   193 
       
   194     iSearchResultsArr.Reset();
       
   195 
       
   196     CleanupStack::PopAndDestroy(); // query
       
   197     delete filterHelper;
       
   198 
       
   199     PRINT ( _L("End CPcsAlgorithm2Helper::SearchMixedL") );
       
   200 
       
   201     __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchMixedL") );
       
   202     }
       
   203 
       
   204 // ----------------------------------------------------------------------------
       
   205 // CPcsAlgorithm2Helper::SearchITUL
       
   206 // Search function for ITU-T style
       
   207 // ----------------------------------------------------------------------------
       
   208 void CPcsAlgorithm2Helper::SearchITUL(const CPsSettings& aSettings,
       
   209                                       CPsQuery& aPsQuery, TBool isSearchInGroup,
       
   210                                       RArray<TInt>& aContactsInGroup,
       
   211                                       RPointerArray<CPsData>& searchResults,
       
   212                                       RPointerArray<CPsPattern>& searchSeqs)
       
   213     {
       
   214     __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchITUL") );
       
   215 
       
   216     PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchITUL") );
       
   217 
       
   218     // Create filtering helper for the required sort type
       
   219     TSortType sortType = aSettings.GetSortType();
       
   220     CPcsAlgorithm2FilterHelper* filterHelper =
       
   221             CPcsAlgorithm2FilterHelper::NewL(sortType);
       
   222 
       
   223     // Convert the query to string
       
   224     TPtrC queryPtr = aPsQuery.QueryAsStringLC();
       
   225 
       
   226     // Search from cache based on first character
       
   227     const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0);
       
   228     TInt numValue  = keyMap->PoolIdForCharacter( firstCharItem.Character() );
       
   229 
       
   230     // Reset the result set array for new search
       
   231     iSearchResultsArr.ResetAndDestroy();
   211     iSearchResultsArr.ResetAndDestroy();
   232 
   212 
   233     // Get the data stores
   213     CleanupStack::PopAndDestroy( filterHelper );
   234     RPointerArray<TDesC> aDataStores;
   214 
   235     aSettings.SearchUrisL(aDataStores);
   215     //__LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchSingleL") );
   236 
   216 
   237     // Get the required display fields from the client
   217     PRINT ( _L("End CPcsAlgorithm2Helper::SearchSingleL") );
   238     RArray<TInt> requiredDataFields;
       
   239     aSettings.DisplayFieldsL(requiredDataFields);
       
   240 
       
   241     // Perform search for each required data store
       
   242     RPointerArray<CPcsPoolElement> elements;
       
   243 
       
   244     for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++)
       
   245         {
       
   246         RPointerArray<CPsData> *temp = new (ELeave) RPointerArray<CPsData> ();
       
   247         iSearchResultsArr.Append(temp);
       
   248 
       
   249         // Get the contents for this data store
       
   250         TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex]));
       
   251         if (arrayIndex < 0)
       
   252             {
       
   253             continue;
       
   254             }
       
   255         CPcsCache* cache = iAlgorithm->GetCache(arrayIndex);
       
   256         cache->GetContactsForKeyL(numValue, elements);
       
   257 
       
   258         // Perform filtering
       
   259         FilterResultsL(filterHelper, elements, queryPtr,
       
   260                        isSearchInGroup, aContactsInGroup);
       
   261 
       
   262         // If alphabetical sorting, get the results for this datastore               
       
   263         if (sortType == EAlphabetical)
       
   264             {
       
   265             filterHelper->GetResults(*(iSearchResultsArr[dsIndex]));
       
   266             }
       
   267 
       
   268         elements.Reset();
       
   269         }
       
   270 
       
   271     aDataStores.ResetAndDestroy();
       
   272     requiredDataFields.Reset();
       
   273 
       
   274     // If alphabetical sorting, merge the result sets of all datastores
       
   275     if (sortType == EAlphabetical)
       
   276         {
       
   277         // Merge the result sets of individual datastores alphabetically
       
   278         CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iSearchResultsArr,
       
   279                                                         searchResults);
       
   280         }
       
   281     else
       
   282         {
       
   283         // Results are already sorted pattern based 
       
   284         filterHelper->GetResults(searchResults);
       
   285         }
       
   286 
       
   287     // Get the sorted match sequence list
       
   288     filterHelper->GetPatternsL(searchSeqs);
       
   289 
       
   290     PRINT1 ( _L("Number of search results = %d"), searchResults.Count() );
       
   291 
       
   292     // Cleanup
       
   293     for (TInt i = 0; i < iSearchResultsArr.Count(); i++)
       
   294         {
       
   295         iSearchResultsArr[i]->Reset();
       
   296         delete iSearchResultsArr[i];
       
   297         iSearchResultsArr[i] = NULL;
       
   298         }
       
   299     iSearchResultsArr.Reset();
       
   300 
       
   301     CleanupStack::PopAndDestroy(); // query
       
   302     delete filterHelper;
       
   303 
       
   304     PRINT ( _L("End CPcsAlgorithm2Helper::SearchITUL") );
       
   305     __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchITUL") );
       
   306     }
       
   307 
       
   308 // ----------------------------------------------------------------------------
       
   309 // CPcsAlgorithm2Helper::SearchQWERTYL
       
   310 // Search function for QWERTY style
       
   311 // ----------------------------------------------------------------------------
       
   312 void CPcsAlgorithm2Helper::SearchQWERTYL(const CPsSettings& aSettings,
       
   313                                          CPsQuery& aPsQuery, TBool isSearchInGroup,
       
   314                                          RArray<TInt>& aContactsInGroup,
       
   315                                          RPointerArray<CPsData>& searchResults,
       
   316                                          RPointerArray<CPsPattern>& searchSeqs)
       
   317     {
       
   318     __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchQWERTYL") );
       
   319     PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchQWERTYL") );
       
   320 
       
   321     // te filtering helper for the required sort type
       
   322     TSortType sortType = aSettings.GetSortType();
       
   323     CPcsAlgorithm2FilterHelper* filterHelper =
       
   324             CPcsAlgorithm2FilterHelper::NewL(sortType);
       
   325 
       
   326     // Convert the query to string
       
   327     TPtrC queryPtr = aPsQuery.QueryAsStringLC();
       
   328 
       
   329     // Search from cache based on first character
       
   330     const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0);
       
   331     TInt numValue  = keyMap->PoolIdForCharacter( firstCharItem.Character() );
       
   332     
       
   333     // Reset the result set array for new search
       
   334     iSearchResultsArr.ResetAndDestroy();
       
   335 
       
   336     // Get the data stores  
       
   337     RPointerArray<TDesC> aDataStores;
       
   338     aSettings.SearchUrisL(aDataStores);
       
   339 
       
   340     // Get the required display fields from the client
       
   341     RArray<TInt> requiredDataFields;
       
   342     aSettings.DisplayFieldsL(requiredDataFields);
       
   343 
       
   344     // Perform search for each of the required data stores
       
   345     RPointerArray<CPcsPoolElement> elements;
       
   346 
       
   347     for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++)
       
   348         {
       
   349 
       
   350         RPointerArray<CPsData> *temp = new (ELeave) RPointerArray<CPsData> ();
       
   351         iSearchResultsArr.Append(temp);
       
   352 
       
   353         // Get the contents for this data store
       
   354         TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex]));
       
   355         if (arrayIndex < 0)
       
   356             {
       
   357             continue;
       
   358             }
       
   359         CPcsCache* cache = iAlgorithm->GetCache(arrayIndex);
       
   360         cache->GetContactsForKeyL(numValue, elements);
       
   361 
       
   362         // Perform filtering
       
   363         FilterResultsQwertyL(filterHelper, elements, queryPtr,
       
   364                              isSearchInGroup, aContactsInGroup);
       
   365 
       
   366         // If alphabetical sorting, get the results for this datastore               
       
   367         if (sortType == EAlphabetical)
       
   368             {
       
   369             filterHelper->GetResults(*(iSearchResultsArr[dsIndex]));
       
   370             }
       
   371 
       
   372         elements.Reset();
       
   373         }
       
   374     aDataStores.ResetAndDestroy();
       
   375     requiredDataFields.Reset();
       
   376 
       
   377     // If alphabetical sorting, merge the result sets of all datastores
       
   378     if (sortType == EAlphabetical)
       
   379         {
       
   380         // Form the complete searchResults array
       
   381         CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iSearchResultsArr,
       
   382                                                         searchResults);
       
   383         }
       
   384     else
       
   385         {
       
   386         // Results are already sorted pattern based
       
   387         filterHelper->GetResults(searchResults);
       
   388         }
       
   389 
       
   390     // Get the sorted match sequence list
       
   391     filterHelper->GetPatternsL(searchSeqs);
       
   392 
       
   393     PRINT1 ( _L("Number of search results = %d"), searchResults.Count() );
       
   394 
       
   395     // Cleanup             
       
   396     for (TInt i = 0; i < iSearchResultsArr.Count(); i++)
       
   397         {
       
   398         iSearchResultsArr[i]->Reset();
       
   399         delete iSearchResultsArr[i];
       
   400         iSearchResultsArr[i] = NULL;
       
   401         }
       
   402     iSearchResultsArr.Reset();
       
   403 
       
   404     CleanupStack::PopAndDestroy(); // query
       
   405     delete filterHelper;
       
   406 
       
   407     PRINT ( _L("End CPcsAlgorithm2Helper::SearchQWERTYL") );
       
   408     __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchQWERTYL") );
       
   409     }
   218     }
   410 
   219 
   411 // ----------------------------------------------------------------------------
   220 // ----------------------------------------------------------------------------
   412 // CPcsAlgorithm2Helper::SearchMatchSeqL
   221 // CPcsAlgorithm2Helper::SearchMatchSeqL
   413 // Funciton to search matching sequences in the input text
   222 // Function to search matching sequences in the input text
   414 // ----------------------------------------------------------------------------
   223 // ----------------------------------------------------------------------------
   415 void CPcsAlgorithm2Helper::SearchMatchSeqL(HBufC* /*aQuery*/, TDesC& aData,
   224 void CPcsAlgorithm2Helper::SearchMatchSeqL(CPsQuery& aPsQuery,
   416                                            RPointerArray<TDesC>& /*aMatchSet*/, 
   225                                            const TDesC& aData,
   417                                            CPsQuery& /*aPsQuery*/,
   226                                            RPointerArray<TDesC>& aMatchSet,
   418                                            RArray<TPsMatchLocation>& aMatchLocation)
   227                                            RArray<TPsMatchLocation>& aMatchLocation )
   419     {
   228     {
   420     PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchMatchSeqL") );
   229     PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchMatchSeqL") );
   421 
   230 
   422     // Convert the data into words		     
   231     RArray<TInt> matchPos;
   423     TLex lex(aData);
   232     CleanupClosePushL( matchPos );
   424 
   233     RArray<TInt> matchLen;
   425     // First word
   234     CleanupClosePushL( matchLen );
   426     TPtrC token = lex.NextToken();
   235     if ( iAlgorithm->FindUtilECE()->MatchRefineL( aData, aPsQuery, matchPos, matchLen, ETrue ) )
   427 
   236         {
   428     TInt beg = lex.Offset() - token.Length(); // start index of match sequence
   237         ASSERT( matchPos.Count() == matchLen.Count() );
   429 
   238         const TInt matchPosCount = matchPos.Count();
   430     // Search thru multiple words
   239         for ( TInt i = 0 ; i < matchPosCount ; ++i )
   431     while (token.Length() != 0)
   240             {
   432         {
   241             TPsMatchLocation tempLocation;
   433         TPsMatchLocation tempLocation;
   242     
   434 
   243             // check for directionality of the text
   435         // check for directionality of the text
   244             TBool found(EFalse);
   436         TBool found(EFalse);
   245             TPtrC matchingPart = aData.Mid( matchPos[i], matchLen[i] );
   437         TBidiText::TDirectionality dir = TBidiText::TextDirectionality(token, &found);
   246             TBidiText::TDirectionality dir = TBidiText::TextDirectionality(matchingPart, &found);
   438 
   247     
   439         tempLocation.index = beg;
   248             tempLocation.index = matchPos[i];
   440         tempLocation.length = 0;
   249             tempLocation.length = matchLen[i];
   441         tempLocation.direction = dir;
   250             tempLocation.direction = dir;
   442 
   251     
   443         // Add the match location to the data structure array
   252             // Add the match location to the data structure array
   444         aMatchLocation.Append(tempLocation);
   253             aMatchLocation.Append(tempLocation);
   445 
   254             
   446         // Next word
   255             // Add the matched sequence to set, not allowing duplicates
   447         token.Set(lex.NextToken());
   256             CPcsAlgorithm2Utils::AppendMatchToSeqL( aMatchSet, matchingPart );
   448         beg = lex.Offset() - token.Length(); // start index of next word
   257             }
   449         }
   258         }
       
   259     CleanupStack::PopAndDestroy( &matchLen );
       
   260     CleanupStack::PopAndDestroy( &matchPos );
   450 
   261 
   451     PRINT ( _L("End CPcsAlgorithm2Helper::SearchMatchSeqL") );
   262     PRINT ( _L("End CPcsAlgorithm2Helper::SearchMatchSeqL") );
   452     }
   263     }
   453 
   264 
   454 // ----------------------------------------------------------------------------
   265 // ----------------------------------------------------------------------------
   455 // CPcsAlgorithm2::FilterResultsL
   266 // CPcsAlgorithm2Helper::FilterResultsSingleL
   456 // Subset search function
   267 // Subset search function
   457 // ----------------------------------------------------------------------------
   268 // ----------------------------------------------------------------------------
   458 void CPcsAlgorithm2Helper::FilterResultsL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper, 
   269 void CPcsAlgorithm2Helper::FilterResultsSingleL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper,
   459                                           RPointerArray<CPcsPoolElement>& searchSet, 
   270                                                 RPointerArray<CPcsPoolElement>& aSearchSet,
   460                                           const TDesC& searchQuery,
   271                                                 CPsQuery& aSearchQuery,
   461                                           TBool isSearchInGroup, 
   272                                                 TUint8 aFilteredDataMatch,
   462                                           RArray<TInt>& aContactsInGroup)
   273                                                 TBool aIsSearchInGroup,
   463     {
   274                                                 const RArray<TInt>& aContactsInGroup)
   464     __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::FilterResultsL") );
   275     {
   465     PRINT ( _L("Enter CPcsAlgorithm2Helper::FilterResultsL") );
   276     PRINT ( _L("Enter CPcsAlgorithm2::FilterResultsSingleL") );
   466 
   277 
   467     // Convert the search condition to numeric key string
   278     TInt maxcount = 0;
   468     TBuf<KPsQueryMaxLen> tmpSearchQuery;
   279     CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
   469     keyMap->GetNumericKeyString(searchQuery, tmpSearchQuery);
   280 
   470     
   281     // Assume that all the elements is aSearchSet are from the same database.
   471     //Holds the first char of first name of a contact
   282     // Get firstname index and lastname index for that database.
   472     TBuf<10> firstChar;   
   283     // If both are found, then name fields are matched a bit differently compared
   473 
   284     // to rest of the fields.
   474     PRINT2 ( _L("Numeric Key String for %S = %S"), &searchQuery, &tmpSearchQuery );
   285     TInt fnIndex( KErrNotFound );
   475 
   286     TInt lnIndex( KErrNotFound );
       
   287     TBool fullNameSearch( EFalse );
       
   288     if ( aSearchSet.Count() )
       
   289         {
       
   290         TInt dbUriId = aSearchSet[0]->GetPsData()->UriId();
       
   291         CPcsCache* cache = iAlgorithm->GetCache( dbUriId );
       
   292         fnIndex = cache->GetFirstNameIndex();
       
   293         lnIndex = cache->GetLastNameIndex();
       
   294 
       
   295         // Ensure that firstname and lastname are among the fields to be searched
       
   296         TUint8 fnBitmask = 1 << fnIndex;
       
   297         TUint8 lnBitmask = 1 << lnIndex;
       
   298         if ( (aFilteredDataMatch & fnBitmask) && 
       
   299              (aFilteredDataMatch & lnBitmask) )
       
   300             {
       
   301             fullNameSearch = ETrue;
       
   302             // Remove firstname and lastname from the set of fields to search
       
   303             // so that they will not be searched twice.
       
   304             aFilteredDataMatch &= ~fnBitmask;
       
   305             aFilteredDataMatch &= ~lnBitmask;
       
   306             }
       
   307         }
       
   308     
   476     // Parse thru each search set elements and filter the results
   309     // Parse thru each search set elements and filter the results
   477     for (int index = 0; index < searchSet.Count(); index++)
   310     const TInt searchSetCount = aSearchSet.Count();
   478         {
   311     for (TInt index = 0; index < searchSetCount; index++)
   479         CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (searchSet[index]);
   312         {
       
   313         CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (aSearchSet[index]);
   480         CPsData* psData = poolElement->GetPsData();
   314         CPsData* psData = poolElement->GetPsData();
   481         psData->ClearDataMatches();
   315         psData->ClearDataMatches();
   482         RPointerArray<TDesC> tempMatchSeq;
   316 
   483 
   317         // Skip the contact if we are doing a group search and contact doesn't belong to the group
   484         // Search thru multiple words
   318         if ( aIsSearchInGroup && 
   485         TBuf<KBufferMaxLen> token;
   319              aContactsInGroup.Find( psData->Id() ) == KErrNotFound )
   486         TBuf<KBufferMaxLen> firstName;
   320             {
   487         TBuf<KBufferMaxLen> lastName;
   321             continue;
   488         lastName.Append(psData->Data(iAlgorithm->GetLastNameIndex())->Des());
   322             }
   489         firstName.Append(psData->Data(iAlgorithm->GetFirstNameIndex())->Des());
   323         
   490 
   324         // Buffer for matched character sequence. Currently, we don't return
   491         CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
   325         // accurate pattern but just first character from the matching point.
   492         TBool matched  = 0;
   326         // Current clients don't actually use this data for anything.
   493 
   327         TBuf<1> matchingData;
   494         // If has Chinese word and the first name doesn't start with Chinese character, then should add a space
   328         
   495         // before the first name, otherwise intitial letter searching will not function
   329         TBool matched = EFalse;
   496         if( pFindUtilEce->IsChineseWord(lastName) || pFindUtilEce->IsChineseWord(firstName))
   330 
   497             {
   331         // Parse thru each data field and filter the results
   498             token.Append(lastName);
   332         // -------------------------------------------------
   499             if (firstName.Length())
   333         
   500                 {
   334         // Name fields are handled separately to enable searching with query like
   501                 firstChar.Zero();
   335         // "LastnameFirstname". Searching fullname by query string 
   502                 firstChar.Append(firstName[0]);
   336         // only for the pool elements matching with the firstname or lastname
   503                 if (!pFindUtilEce->IsChineseWord(firstChar) )
   337         if ( fullNameSearch && ( poolElement->IsDataMatch(fnIndex) || 
   504                     {
   338             poolElement->IsDataMatch(lnIndex) ))
   505                     token.Append(KSpace);
   339             {
   506                     }
   340             HBufC* fullName = CreateNameBufLC( *psData, fnIndex, lnIndex );
   507                 token.Append(firstName);
   341 
   508                 }
   342             // FindUtil can take care of matching queries like "Firstname", "Lastname", 
   509 
   343             // and "LastnameFirstname".
   510             if (token.Length() != 0)
   344             matched = pFindUtilEce->MatchRefineL( *fullName, aSearchQuery );
   511                 {
   345             if (matched)
   512                 matched = iAlgorithm->FindUtil()->Interface()->
   346                 {
   513                     MatchRefineL(token, tmpSearchQuery, ECustomConverter, iAlgorithm);
   347                 matchingData = fullName->Left(1);
   514 
   348                 psData->SetDataMatch( fnIndex );
       
   349                 psData->SetDataMatch( lnIndex );
       
   350                 }
       
   351             
       
   352             CleanupStack::PopAndDestroy( fullName );
       
   353             }
       
   354 
       
   355         // Find from the rest of the fields if no match found so far. 
       
   356         // Name fields are already removed from aFilteredDataMatch if we did separate full name search.
       
   357         const TInt dataElementCount = psData->DataElementCount();
       
   358         for ( TInt dataIndex = 0; dataIndex < dataElementCount && !matched ; dataIndex++ )
       
   359             {
       
   360             // Filter off data fields not required in search
       
   361             TUint8 bitIndex = 1 << dataIndex;
       
   362             TUint8 filter = bitIndex & aFilteredDataMatch;
       
   363             if ( filter == 0x0 )
       
   364                 {
       
   365                 // Move to next data
       
   366                 continue;
       
   367                 }
       
   368 
       
   369             if ( poolElement->IsDataMatch(dataIndex) )
       
   370                 {
       
   371                 TPtrC fieldData( *psData->Data(dataIndex) );
       
   372                 matched = pFindUtilEce->MatchRefineL( fieldData, aSearchQuery );
   515                 if (matched)
   373                 if (matched)
   516                     {
   374                     {
   517                     psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
   375                     matchingData = fieldData.Left(1);
   518                     psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
   376                     psData->SetDataMatch( dataIndex );
   519                     }
   377                     }
   520                 }
   378                 }
   521             }
   379             }
   522         else
   380 
   523             {
   381 
   524             // If contact name only has western word, then should send 
   382         // Add to results if match is found
   525             // "first name","last name" and "last name + first name" to FindUtil to do the search
   383         if ( matched )
   526             const TInt lastnameLen = lastName.Length();
   384             {
   527             const TInt firstnameLen = firstName.Length();
   385             RPointerArray<TDesC> tempMatchSeq;
   528             if(lastnameLen)
   386             CleanupClosePushL( tempMatchSeq );
   529                 {
   387 
   530                 matched = iAlgorithm->FindUtil()->Interface()->
   388             // Wrap matched character sequence to array.
   531                     MatchRefineL(lastName, tmpSearchQuery, ECustomConverter, iAlgorithm);
   389             matchingData.UpperCase();
   532 
   390             tempMatchSeq.AppendL(&matchingData);
   533                 if (matched)
   391             
   534                     {
   392             // Add the result
   535                     psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
   393             aAlgorithmFilterHelper->AddL( psData, tempMatchSeq );
   536                     }
   394             maxcount++;
   537                 }
   395             
   538 
   396             // Cleanup the match sequence array as 
   539             if(!matched && firstnameLen)
   397             // they are stored in pattern details structure
   540                 {
   398             CleanupStack::PopAndDestroy( &tempMatchSeq ); // Close
   541                 matched = iAlgorithm->FindUtil()->Interface()->
   399             
   542                     MatchRefineL(firstName, tmpSearchQuery, ECustomConverter, iAlgorithm);
   400             // TODO: Match seqs could be extracted from actual
   543 
   401             //       match locations by using the other overload of
   544                 if (matched)
   402             //       CFindUtilChineseECE::MatchRefineL().
   545                     {
   403             //       Currently, match seq data is not used by clients.
   546                     psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
       
   547                     }
       
   548                 }
       
   549             
       
   550             token.Append(lastName);
       
   551             token.Append(firstName);
       
   552             if (!matched && lastnameLen && firstnameLen)
       
   553                 {
       
   554                 matched = iAlgorithm->FindUtil()->Interface()->
       
   555                     MatchRefineL(token, tmpSearchQuery, ECustomConverter, iAlgorithm);
       
   556 
       
   557                 if (matched)
       
   558                     {
       
   559                     psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
       
   560                     psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
       
   561                     }
       
   562                 }
       
   563             }
       
   564 
       
   565         if (matched)
       
   566             {
       
   567             // Extract matched character sequence, don't need to be accurate for Chinese variant
       
   568             const TInt len = 1;  
       
   569             HBufC* seq = HBufC::NewLC(len);
       
   570             *seq = token.Mid(0, len);
       
   571             seq->Des().UpperCase();
       
   572 
       
   573             TIdentityRelation<TDesC> rule(Compare1);
       
   574             if (tempMatchSeq.Find(seq, rule) == KErrNotFound)
       
   575                 {
       
   576                 tempMatchSeq.Append(seq);
       
   577                 CleanupStack::Pop();
       
   578                 }
       
   579             else
       
   580                 {
       
   581                 CleanupStack::PopAndDestroy();
       
   582                 }
       
   583                 
       
   584 
       
   585             // Add the result        
       
   586             if (isSearchInGroup)
       
   587                 {
       
   588                 if (aContactsInGroup.Find(psData->Id()) != KErrNotFound)
       
   589                     {
       
   590                     aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
       
   591                     }
       
   592                 }
       
   593             else
       
   594                 {
       
   595                 aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
       
   596                 }
       
   597             }
       
   598 
       
   599         // Cleanup the match sequence array as 
       
   600         // they are stored in pattern details structure
       
   601         tempMatchSeq.ResetAndDestroy();
       
   602         }
       
   603 
       
   604     PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsL") );
       
   605     __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::FilterResultsL") );
       
   606     }
       
   607 
       
   608 // ----------------------------------------------------------------------------
       
   609 // CPcsAlgorithm2Helper::FilterResultsQwertyL
       
   610 // Subset search function 
       
   611 // ----------------------------------------------------------------------------
       
   612 void CPcsAlgorithm2Helper::FilterResultsQwertyL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper, 
       
   613                                                 RPointerArray<CPcsPoolElement>& searchSet, 
       
   614                                                 const TDesC& searchQuery,TBool isSearchInGroup, 
       
   615                                                 RArray<TInt>& aContactsInGroup)
       
   616     {
       
   617     PRINT ( _L("Enter CPcsAlgorithm2::FilterResultsQwertyL") );
       
   618 
       
   619     TBuf<50> tmpSearchQuery = searchQuery;
       
   620     tmpSearchQuery.LowerCase();
       
   621     
       
   622     //Holds the first char of first name of a contact
       
   623     TBuf<10> firstChar;
       
   624 
       
   625     // Parse thru each search set elements and filter the results    
       
   626     for (int index = 0; index < searchSet.Count(); index++)
       
   627         {
       
   628         CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (searchSet[index]);
       
   629         CPsData* psData = poolElement->GetPsData();
       
   630         psData->ClearDataMatches();
       
   631         RPointerArray<TDesC> tempMatchSeq;
       
   632 
       
   633         // Parse thru each data and filter the results
       
   634         TBuf<KBufferMaxLen> token;
       
   635         TBuf<KBufferMaxLen> firstName;
       
   636         TBuf<KBufferMaxLen> lastName;
       
   637         lastName.Append(psData->Data(iAlgorithm->GetLastNameIndex())->Des());
       
   638         firstName.Append(psData->Data(iAlgorithm->GetFirstNameIndex())->Des());
       
   639 
       
   640         CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
       
   641         TBool matched  = 0;
       
   642 
       
   643         // If has Chinese word and the first name doesn't start with Chinese character, then should add a space
       
   644         // before the first name, otherwise intitial letter searching will not function
       
   645         if( pFindUtilEce->IsChineseWord(lastName) || pFindUtilEce->IsChineseWord(firstName))
       
   646             {
       
   647             token.Append(lastName);
       
   648             if (firstName.Length())
       
   649                 {
       
   650                 firstChar.Zero();
       
   651                 firstChar.Append(firstName[0]);
       
   652                 if (!pFindUtilEce->IsChineseWord(firstChar) )
       
   653                     {
       
   654                     token.Append(KSpace);
       
   655                     }
       
   656                 token.Append(firstName);
       
   657                 }
       
   658 
       
   659             if (token.Length() != 0)
       
   660                 {
       
   661                 matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(token, tmpSearchQuery);
       
   662 
       
   663                 if (matched)
       
   664                     {
       
   665                     psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
       
   666                     psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
       
   667                     }
       
   668                 }
       
   669             }
       
   670         else
       
   671             {
       
   672             // If contact name only has western word, then should send 
       
   673             // "first name","last name" and "last name + first name" to FindUtil to do the search
       
   674             const TInt lastnameLen = lastName.Length();
       
   675             const TInt firstnameLen = firstName.Length();
       
   676             if(lastnameLen)
       
   677                 {
       
   678                 matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(lastName, tmpSearchQuery);
       
   679 
       
   680                 if (matched)
       
   681                     {
       
   682                     psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
       
   683                     }
       
   684                 }
       
   685 
       
   686             if(!matched && firstnameLen)
       
   687                 {
       
   688                 matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(firstName, tmpSearchQuery);
       
   689 
       
   690                 if (matched)
       
   691                     {
       
   692                     psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
       
   693                     }
       
   694                 }
       
   695             
       
   696             token.Append(lastName);
       
   697             token.Append(firstName);
       
   698             if (!matched && lastnameLen && firstnameLen)
       
   699                 {
       
   700                 matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(token, tmpSearchQuery);
       
   701 
       
   702                 if (matched)
       
   703                     {
       
   704                     psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
       
   705                     psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
       
   706                     }
       
   707                 }
       
   708             }
   404             }
   709         
   405         
   710         if (matched)
   406           if ( iMaxCount != -1 && maxcount > iMaxCount )
   711             {
   407               {
   712             // Extract matched character sequence, don't need to be accurate for Chinese variant
   408               return;
   713             const TInt len = 1;
   409               }
   714             HBufC* seq = HBufC::NewLC(len);
   410         }
   715             *seq = token.Mid(0, len);
   411 
   716             seq->Des().UpperCase();
   412     PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsSingleL") );
   717 
       
   718             TIdentityRelation<TDesC> rule(Compare1);
       
   719             if (tempMatchSeq.Find(seq, rule) == KErrNotFound)
       
   720                 {
       
   721                 tempMatchSeq.Append(seq);
       
   722                 CleanupStack::Pop();
       
   723                 }
       
   724             else
       
   725                 {
       
   726                 CleanupStack::PopAndDestroy();
       
   727                 }
       
   728             
       
   729             // Add the result
       
   730             if (isSearchInGroup)
       
   731                 {
       
   732                 if (aContactsInGroup.Find(psData->Id()) != KErrNotFound)
       
   733                     {
       
   734                     aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
       
   735                     }
       
   736                 }
       
   737             else
       
   738                 {
       
   739                 aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
       
   740                 }
       
   741             }
       
   742 
       
   743         // Cleanup the match sequence array as 
       
   744         // they are stored in pattern details structure
       
   745         tempMatchSeq.ResetAndDestroy();
       
   746         }
       
   747 
       
   748     PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsQwertyL") );
       
   749     }
       
   750 
       
   751 // ----------------------------------------------------------------------------
       
   752 // CPcsAlgorithm2Helper::FilterResultsMixedL
       
   753 // Subset search function
       
   754 // ----------------------------------------------------------------------------
       
   755 void CPcsAlgorithm2Helper::FilterResultsMixedL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper, 
       
   756                                                RPointerArray<CPcsPoolElement>& searchSet, 
       
   757                                                CPsQuery& searchQuery, TBool isSearchInGroup,
       
   758                                                RArray<TInt>& aContactsInGroup)
       
   759     {
       
   760     PRINT ( _L("Enter CPcsAlgorithm2::FilterResultsMixedL") );
       
   761 
       
   762     // Convert the search query to alpha numeric string
       
   763     TBuf<50> tmpSearchQuery;
       
   764     ExtractQueryL(searchQuery, tmpSearchQuery);
       
   765     tmpSearchQuery.LowerCase();
       
   766     TBuf<10> firstChar;
       
   767 
       
   768     // Parse thru each search set elements and filter the results    
       
   769     for (int index = 0; index < searchSet.Count(); index++)
       
   770         {
       
   771         CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (searchSet[index]);
       
   772         CPsData* psData = poolElement->GetPsData();
       
   773         psData->ClearDataMatches();
       
   774         RPointerArray<TDesC> tempMatchSeq;
       
   775 
       
   776         // Parse thru each data and filter the results
       
   777         TBuf<255> token;
       
   778         TBuf<KBufferMaxLen> firstName;
       
   779         TBuf<KBufferMaxLen> lastName;
       
   780         lastName.Append(psData->Data(iAlgorithm->GetLastNameIndex())->Des());
       
   781         firstName.Append(psData->Data(iAlgorithm->GetFirstNameIndex())->Des());
       
   782 
       
   783         CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
       
   784         TBool matched  = 0;
       
   785 
       
   786         // If has Chinese word and the first name doesn't start with Chinese character, then should add a space
       
   787         // before the first name, otherwise intitial letter searching will not function
       
   788         if( pFindUtilEce->IsChineseWord(lastName) || pFindUtilEce->IsChineseWord(firstName))
       
   789             {
       
   790             token.Append(lastName);
       
   791             if (firstName.Length())
       
   792                 {
       
   793                 firstChar.Zero();
       
   794                 firstChar.Append(firstName[0]);
       
   795                 if (!pFindUtilEce->IsChineseWord(firstChar) )
       
   796                     {
       
   797                     token.Append(KSpace);
       
   798                     }
       
   799                 token.Append(firstName);
       
   800                 }
       
   801 
       
   802             if (token.Length() != 0)
       
   803                 {
       
   804                 matched = pFindUtilEce->MatchRefineL(token, searchQuery);
       
   805 
       
   806                 if (matched)
       
   807                     {
       
   808                     psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
       
   809                     psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
       
   810                     }
       
   811                 }
       
   812             }
       
   813         else
       
   814             {
       
   815             // If contact name only has western word, then should send 
       
   816             // "first name","last name" and "last name + first name" to FindUtil to do the search
       
   817             const TInt lastnameLen = lastName.Length();
       
   818             const TInt firstnameLen = firstName.Length();
       
   819             if(lastnameLen)
       
   820                 {
       
   821                 matched = pFindUtilEce->MatchRefineL(lastName, searchQuery);
       
   822 
       
   823                 if (matched)
       
   824                     {
       
   825                     psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
       
   826                     }
       
   827                 }
       
   828 
       
   829             if(!matched && firstnameLen)
       
   830                 {
       
   831                 matched = pFindUtilEce->MatchRefineL(firstName, searchQuery);
       
   832 
       
   833                 if (matched)
       
   834                     {
       
   835                     psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
       
   836                     }
       
   837                 }
       
   838             
       
   839             token.Append(lastName);
       
   840             token.Append(firstName);
       
   841             if (!matched && lastnameLen && firstnameLen)
       
   842                 {
       
   843                 matched = pFindUtilEce->MatchRefineL(token, searchQuery);
       
   844 
       
   845                 if (matched)
       
   846                     {
       
   847                     psData->SetDataMatch(iAlgorithm->GetLastNameIndex());
       
   848                     psData->SetDataMatch(iAlgorithm->GetFirstNameIndex());
       
   849                     }
       
   850                 }
       
   851             }
       
   852 
       
   853         if (matched)
       
   854             {
       
   855             // Extract matched character sequence, don't need to be accurate for Chinese variant
       
   856             const TInt len = 1;       
       
   857         
       
   858             HBufC* seq = HBufC::NewLC(len);
       
   859             *seq = token.Mid(0, len);
       
   860             seq->Des().UpperCase();
       
   861 
       
   862             TIdentityRelation<TDesC> rule(Compare1);
       
   863             if (tempMatchSeq.Find(seq, rule) == KErrNotFound)
       
   864                 {
       
   865                 tempMatchSeq.Append(seq);
       
   866                 CleanupStack::Pop();
       
   867                 }
       
   868             else
       
   869                 {
       
   870                 CleanupStack::PopAndDestroy();
       
   871                 }
       
   872             
       
   873             // Add the result
       
   874             if (isSearchInGroup)
       
   875                 {
       
   876                 if (aContactsInGroup.Find(psData->Id()) != KErrNotFound)
       
   877                     {
       
   878                     aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
       
   879                     }
       
   880                 }
       
   881             else
       
   882                 {
       
   883                 aAlgorithmFilterHelper->AddL(psData, tempMatchSeq);
       
   884                 }
       
   885             }
       
   886 
       
   887         // Cleanup the match sequence array as 
       
   888         // they are stored in pattern details structure
       
   889         tempMatchSeq.ResetAndDestroy();
       
   890         }
       
   891 
       
   892     PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsMixedL") );
       
   893     }
   413     }
   894 
   414 
   895 // ----------------------------------------------------------------------------
   415 // ----------------------------------------------------------------------------
   896 // CPcsAlgorithm2Helper::SortSearchSeqsL()
   416 // CPcsAlgorithm2Helper::SortSearchSeqsL()
   897 // 
   417 // 
   898 // ----------------------------------------------------------------------------
   418 // ----------------------------------------------------------------------------
   899 void CPcsAlgorithm2Helper::SortSearchSeqsL(RPointerArray<TDesC>& aSearchSeqs)
   419 void CPcsAlgorithm2Helper::SortSearchSeqsL(RPointerArray<TDesC>& aSearchSeqs)
   900     {
   420     {
   901     // Sort the search seqs
   421     // Sort the search seqs
   902     TLinearOrder<TDesC> rule(Compare2);
   422     TLinearOrder<TDesC> rule( CPcsAlgorithm2Utils::MyCompareC );
   903     aSearchSeqs.Sort(rule);
   423     aSearchSeqs.Sort(rule);
   904     }
   424     }
   905 
   425 
   906 // ----------------------------------------------------------------------------
   426 // ---------------------------------------------------------------------------
   907 // CPcsAlgorithm2Helper::ExtractQueryL()
   427 // CPcsAlgorithm2Helper::CreteNameBufLC
   908 // Required for mixed mode search.
   428 // Update name order according to Phonebook setting
   909 // ----------------------------------------------------------------------------
   429 // ---------------------------------------------------------------------------
   910 void CPcsAlgorithm2Helper::ExtractQueryL(CPsQuery& aQuery, TDes& aOutput)
   430 HBufC* CPcsAlgorithm2Helper::CreateNameBufLC( const CPsData& aContactData, 
   911     {
   431         TInt aFirstNameIndex, TInt aLastNameIndex ) const
   912     for (int i = 0; i < aQuery.Count(); i++)
   432     {
   913         {
   433     const TDesC& firstName( *aContactData.Data(aFirstNameIndex) );
   914         if (aQuery.GetItemAtL(i).Mode() == EItut)
   434     const TDesC& lastName( *aContactData.Data(aLastNameIndex) );
   915             {
   435     CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE();
   916             TBuf<KPsQueryMaxLen> outBuf;
   436     HBufC* fullName = NULL;
   917             keyMap->GetNumericKeyString(aQuery.QueryAsStringLC(), outBuf);
   437     
   918             aOutput.Append(outBuf[i]);
   438     if ( pFindUtilEce->IsChineseWordIncluded( lastName ) || 
   919             CleanupStack::PopAndDestroy();
   439         pFindUtilEce->IsChineseWordIncluded( firstName ) )
       
   440         {
       
   441         fullName = HBufC::NewLC( lastName.Length() + firstName.Length()  + 1 );
       
   442         TPtr fullNamePtr = fullName->Des();
       
   443     
       
   444         // Form the full name according the Phonebook name order setting. Typically,
       
   445         // the order is always lastname-firstname in Chinese variants. However, at least
       
   446         // currently it is possible to change this from Contacts app if UI language has
       
   447         // been set to English.
       
   448         if ( iNameOrder == ELastnameFirstname )
       
   449             {
       
   450             fullNamePtr.Append( lastName );
       
   451             //Holds the first char of first name of a contact
       
   452             TBuf<10> firstChar;   
       
   453             firstChar.Zero();
       
   454             
       
   455             if(firstName.Length())
       
   456                 {
       
   457                 firstChar.Append(firstName[0]);   
       
   458                 // There is no space between LastName and FirstName in Chinese Name
       
   459                 // except that the firstChar of FirstName isn't Chinese character
       
   460                 if ( !pFindUtilEce->IsChineseWordIncluded( firstChar ) )
       
   461                     {
       
   462                     fullNamePtr.Append( KSpace );
       
   463                     }
       
   464                 fullNamePtr.Append( firstName ); 
       
   465                 }
   920             }
   466             }
   921         else
   467         else
   922             {
   468             {
   923             aOutput.Append(aQuery.GetItemAtL(i).Character());
   469             fullNamePtr.Append( firstName );
   924             }
   470             //Holds the first char of last name of a contact
   925         }
   471             TBuf<10> firstChar;   
   926     }
   472             firstChar.Zero();
   927 
   473             
   928 // ----------------------------------------------------------------------------
   474             if(lastName.Length())
   929 // CPcsAlgorithm2Helper::ExtractQueryL()
   475                 {
   930 // Required for mixed mode search.
   476                 firstChar.Append(lastName[0]);
   931 // ----------------------------------------------------------------------------
   477                 // There is no space between LastName and FirstName in Chinese Name
   932 void CPcsAlgorithm2Helper::ExtractQueryL(TDesC& aInput, CPsQuery& aQuery, TDes& aOutput)
   478                 // except that the firstChar of Lastname isn't Chinese character  
   933     {
   479                 if ( !pFindUtilEce->IsChineseWordIncluded( firstChar ) )
   934     TInt len = -1;
   480                     {
   935 
   481                     fullNamePtr.Append( KSpace );
   936     if (aInput.Length() > aQuery.Count())
   482                     }
   937         {
   483                 fullNamePtr.Append( lastName ); 
   938         len = aQuery.Count();
   484                 }
       
   485             }
   939         }
   486         }
   940     else
   487     else
   941         {
   488         {
   942         len = aInput.Length();
   489         fullName = HBufC::NewLC( lastName.Length() + firstName.Length() + 1 );
   943         }
   490         TPtr fullNamePtr = fullName->Des();
   944 
   491     
   945     for (int i = 0; i < len; i++)
   492         // Form the full name according the Phonebook name order setting. Typically,
   946         {
   493         // the order is always lastname-firstname in Chinese variants. However, at least
   947         if (aQuery.GetItemAtL(i).Mode() == EItut)
   494         // currently it is possible to change this from Contacts app if UI language has
   948             {
   495         // been set to English.
   949             TBuf<KPsQueryMaxLen> outBuf;
   496         if ( iNameOrder == ELastnameFirstname )
   950             keyMap->GetNumericKeyString(aInput, outBuf);
   497             {
   951             aOutput.Append(outBuf[i]);
   498             fullNamePtr.Append( lastName );
       
   499             fullNamePtr.Append( KSpace );
       
   500             fullNamePtr.Append( firstName );
   952             }
   501             }
   953         else
   502         else
   954             {
   503             {
   955             aOutput.Append(aInput[i]);
   504             fullNamePtr.Append( firstName );
   956             }
   505             fullNamePtr.Append( KSpace );
   957         }
   506             fullNamePtr.Append( lastName );
   958     }
   507             }
   959 
   508         }
   960 // ----------------------------------------------------------------------------
   509     
   961 // CPcsAlgorithm2Helper::FilterDataFieldsL()
   510     return fullName;
   962 // Constructs a bit pattern using the required/supported data fields
   511     }
   963 // For example, 6, 4 and 27 are supported fields <-- 00000111
   512 
   964 //              6 and 4 are required fields      <-- 00000011
   513 // ---------------------------------------------------------------------------
   965 // Bit pattern returned is 00000011.
   514 // CPcsAlgorithm2Helper::UpdateNameOrderL
   966 // ----------------------------------------------------------------------------
   515 // Update name order according to Phonebook setting
   967 TUint8 CPcsAlgorithm2Helper::FilterDataFieldsL(RArray<TInt>& aRequiredDataFields, 
   516 // ---------------------------------------------------------------------------
   968                                                RArray<TInt>& aSupportedDataFields)
   517 void CPcsAlgorithm2Helper::UpdateNameOrderL()
   969     {
   518     {
   970     TUint8 filteredMatch = 0x0;
   519     /*
   971 
   520     * Phonebook name ordering flag, integer value, possible values:
   972     for (int i = 0; i < aSupportedDataFields.Count(); i++)
   521     * 0: name order Lastname Firstname
   973         {
   522     * 1: name order Firstname Lastname
   974         for (int j = 0; j < aRequiredDataFields.Count(); j++)
   523     * 2: name order undefined
   975             {
   524     */
   976             if (aSupportedDataFields[i] == aRequiredDataFields[j])
   525     TInt nameOrderSetting;
   977                 {
   526     iPbkSettings->Get( MPbkGlobalSetting::ENameOrdering, nameOrderSetting );
   978                 TReal val;
   527     
   979                 Math::Pow(val, 2, i);
   528     switch ( nameOrderSetting )
   980 
   529         {
   981                 filteredMatch |= (TUint8) val;
   530         case 0:
   982                 }
   531             {
   983             }
   532             iNameOrder = ELastnameFirstname;
   984         }
   533             break;
   985 
   534             }
   986     return filteredMatch;
   535         case 1:
       
   536             {
       
   537             iNameOrder = EFirstnameLastname;
       
   538             break;
       
   539             }
       
   540         case 2:
       
   541         default:
       
   542             {
       
   543             // Decide name order based on UI language: lastname-firstname
       
   544             // for Chinese, firstname-lastname for the rest of languages.
       
   545             TLanguage uiLang = User::Language();
       
   546             if ( uiLang == ELangPrcChinese || 
       
   547                  uiLang == ELangHongKongChinese ||
       
   548                  uiLang == ELangTaiwanChinese )
       
   549                 {
       
   550                 iNameOrder = ELastnameFirstname;
       
   551                 }
       
   552             else
       
   553                 {
       
   554                 iNameOrder = EFirstnameLastname;
       
   555                 }
       
   556             }
       
   557         }
       
   558     }
       
   559 
       
   560 // ---------------------------------------------------------------------------
       
   561 // CPcsAlgorithm2Helper::SettingChangedL
       
   562 // From MPbkGlobalSettingObserver
       
   563 // ---------------------------------------------------------------------------
       
   564 void CPcsAlgorithm2Helper::SettingChangedL( MPbkGlobalSetting::TPbkGlobalSetting aKey )
       
   565     {
       
   566     if ( aKey == MPbkGlobalSetting::ENameOrdering )
       
   567         {
       
   568         UpdateNameOrderL();
       
   569         }
   987     }
   570     }
   988 
   571 
   989 // End of file
   572 // End of file
   990 
   573 
   991 
   574