diff -r 6b5524b4f673 -r 38bb213f60ba predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsAlgorithm2Helper.cpp --- a/predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsAlgorithm2Helper.cpp Wed Sep 15 11:56:55 2010 +0300 +++ b/predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsAlgorithm2Helper.cpp Wed Oct 13 14:15:33 2010 +0300 @@ -16,7 +16,7 @@ */ // INCLUDES -#include +#include #include "FindUtilChineseECE.h" #include "CPcsAlgorithm2.h" #include "CPcsAlgorithm2Helper.h" @@ -25,11 +25,22 @@ #include "CPcsCache.h" #include "CPcsKeyMap.h" #include "CPsData.h" +#include "CWords.h" #include "CPsQuery.h" #include "CPsQueryItem.h" #include "CPsDataPluginInterface.h" #include "CPcsPoolElement.h" +// Compare functions +TBool Compare1(const TDesC& aFirst, const TDesC& aSecond) + { + return aFirst == aSecond; + } + +TBool Compare2(const TDesC& aFirst, const TDesC& aSecond) + { + return CPcsAlgorithm2Utils::MyCompareC(aFirst, aSecond); + } // ============================== MEMBER FUNCTIONS ============================ @@ -59,7 +70,6 @@ { PRINT ( _L("Enter CPcsAlgorithm2Helper::CPcsAlgorithm2") ); PRINT ( _L("End CPcsAlgorithm2Helper::CPcsAlgorithm2") ); - iMaxCount = 0; } // ---------------------------------------------------------------------------- @@ -71,18 +81,13 @@ PRINT ( _L("Enter CPcsAlgorithm2Helper::ConstructL") ); iAlgorithm = aAlgorithm; - iKeyMap = iAlgorithm->GetKeyMap(); + keyMap = iAlgorithm->GetKeyMap(); - iPbkSettings = PbkGlobalSettingFactory::CreatePersistentSettingL(); - iPbkSettings->ConnectL( MPbkGlobalSetting::EGeneralSettingCategory ); - iPbkSettings->RegisterObserverL( this ); - UpdateNameOrderL(); - PRINT ( _L("End CPcsAlgorithm2Helper::ConstructL") ); } // ---------------------------------------------------------------------------- -// CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper +// CPcsAlgorithm2Helper::CPcsAlgorithm2Helper // Destructor // ---------------------------------------------------------------------------- CPcsAlgorithm2Helper::~CPcsAlgorithm2Helper() @@ -93,323 +98,798 @@ } // ---------------------------------------------------------------------------- -// CPcsAlgorithm2Helper::SearchSingleL +// CPcsAlgorithm2Helper::SearchMixedL // Search function for input with both ITU-T and QWERTY mode // ---------------------------------------------------------------------------- -void CPcsAlgorithm2Helper::SearchSingleL(const CPsSettings& aSettings, - CPsQuery& aPsQuery, - TBool aIsSearchInGroup, - const RArray& aContactsInGroup, - RPointerArray& aSearchResults, - RPointerArray& aSearchSeqs) +void CPcsAlgorithm2Helper::SearchMixedL(const CPsSettings& aSettings, + CPsQuery& aPsQuery, TBool isSearchInGroup, + RArray& aContactsInGroup, + RPointerArray& searchResults, + RPointerArray& searchSeqs) { - PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchSingleL") ); + __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchMixedL") ); - //__LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchSingleL") ); + PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchMixedL") ); - iMaxCount = aSettings.MaxResults(); - // Create filtering helper for the required sort type TSortType sortType = aSettings.GetSortType(); CPcsAlgorithm2FilterHelper* filterHelper = CPcsAlgorithm2FilterHelper::NewL(sortType); - CleanupStack::PushL( filterHelper ); - - // Search from cache based on first character - const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0); - TInt cachePoolId = iKeyMap->PoolIdForCharacter( firstCharItem.Character(), firstCharItem.Mode() ); // Reset the result set array for new search iSearchResultsArr.ResetAndDestroy(); // Get the data stores - RPointerArray dataStores; - CleanupResetAndDestroyPushL( dataStores ); - aSettings.SearchUrisL(dataStores); + RPointerArray aDataStores; + aSettings.SearchUrisL(aDataStores); // Get the required display fields from the client RArray requiredDataFields; - CleanupClosePushL( requiredDataFields ); aSettings.DisplayFieldsL(requiredDataFields); + + // Search from cache based on first character + const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0); + TInt numValue = keyMap->PoolIdForCharacter( firstCharItem.Character() ); // Perform search for each required data store RPointerArray elements; - CleanupClosePushL( elements ); - const TInt dataStoresCount = dataStores.Count(); - for (TInt dsIndex = 0; dsIndex < dataStoresCount; dsIndex++) + for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++) { - RPointerArray* temp = new (ELeave) RPointerArray (); - CleanupStack::PushL( temp ); - iSearchResultsArr.AppendL( temp ); - CleanupStack::Pop( temp ); + + RPointerArray *temp = new (ELeave) RPointerArray (); + iSearchResultsArr.Append(temp); // Get the contents for this data store - TInt arrayIndex = iAlgorithm->GetCacheIndex(*(dataStores[dsIndex])); + TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex])); if (arrayIndex < 0) { continue; } CPcsCache* cache = iAlgorithm->GetCache(arrayIndex); - cache->GetContactsForKeyL(cachePoolId, elements); - - // Get the supported data fields for this data store - RArray supportedDataFields; - CleanupClosePushL( supportedDataFields ); - cache->GetDataFields(supportedDataFields); - - // Get the filtered data fields for this data store - TUint8 filteredDataMatch = CPcsAlgorithm2Utils::FilterDataFieldsL(requiredDataFields, - supportedDataFields); + cache->GetContactsForKeyL(numValue, elements); // Perform filtering - FilterResultsSingleL(filterHelper, - elements, - aPsQuery, - filteredDataMatch, - aIsSearchInGroup, - aContactsInGroup); + FilterResultsMixedL(filterHelper, elements, aPsQuery, + isSearchInGroup, aContactsInGroup); - // If alphabetical sorting, get the results for this datastore + // If alphabetical sorting, get the results for this datastore if (sortType == EAlphabetical) { filterHelper->GetResults(*(iSearchResultsArr[dsIndex])); } elements.Reset(); - CleanupStack::PopAndDestroy( &supportedDataFields ); // Close + } + + aDataStores.ResetAndDestroy(); + requiredDataFields.Reset(); + + // If alphabetical sorting, merge the result sets of all datastores + if (sortType == EAlphabetical) + { + // Form the complete searchResults array + CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iSearchResultsArr, + searchResults); + } + else + { + // Results are already sorted pattern based + filterHelper->GetResults(searchResults); + } + + // Get the sorted match sequence list + filterHelper->GetPatternsL(searchSeqs); + + PRINT1 ( _L("Number of search results = %d"), searchResults.Count() ); + + // Cleanup + for (TInt i = 0; i < iSearchResultsArr.Count(); i++) + { + iSearchResultsArr[i]->Reset(); + delete iSearchResultsArr[i]; + iSearchResultsArr[i] = NULL; } - CleanupStack::PopAndDestroy( &elements ); // Close - CleanupStack::PopAndDestroy( &requiredDataFields ); // Close - CleanupStack::PopAndDestroy( &dataStores ); // ResetAndDestroy + iSearchResultsArr.Reset(); + + CleanupStack::PopAndDestroy(); // query + delete filterHelper; + + PRINT ( _L("End CPcsAlgorithm2Helper::SearchMixedL") ); + + __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchMixedL") ); + } + +// ---------------------------------------------------------------------------- +// CPcsAlgorithm2Helper::SearchITUL +// Search function for ITU-T style +// ---------------------------------------------------------------------------- +void CPcsAlgorithm2Helper::SearchITUL(const CPsSettings& aSettings, + CPsQuery& aPsQuery, TBool isSearchInGroup, + RArray& aContactsInGroup, + RPointerArray& searchResults, + RPointerArray& searchSeqs) + { + __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchITUL") ); + + PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchITUL") ); + + // Create filtering helper for the required sort type + TSortType sortType = aSettings.GetSortType(); + CPcsAlgorithm2FilterHelper* filterHelper = + CPcsAlgorithm2FilterHelper::NewL(sortType); + + // Convert the query to string + TPtrC queryPtr = aPsQuery.QueryAsStringLC(); + + // Search from cache based on first character + const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0); + TInt numValue = keyMap->PoolIdForCharacter( firstCharItem.Character() ); + + // Reset the result set array for new search + iSearchResultsArr.ResetAndDestroy(); + + // Get the data stores + RPointerArray aDataStores; + aSettings.SearchUrisL(aDataStores); + + // Get the required display fields from the client + RArray requiredDataFields; + aSettings.DisplayFieldsL(requiredDataFields); + + // Perform search for each required data store + RPointerArray elements; + + for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++) + { + RPointerArray *temp = new (ELeave) RPointerArray (); + iSearchResultsArr.Append(temp); + + // Get the contents for this data store + TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex])); + if (arrayIndex < 0) + { + continue; + } + CPcsCache* cache = iAlgorithm->GetCache(arrayIndex); + cache->GetContactsForKeyL(numValue, elements); + + // Perform filtering + FilterResultsL(filterHelper, elements, queryPtr, + isSearchInGroup, aContactsInGroup); + + // If alphabetical sorting, get the results for this datastore + if (sortType == EAlphabetical) + { + filterHelper->GetResults(*(iSearchResultsArr[dsIndex])); + } + + elements.Reset(); + } + + aDataStores.ResetAndDestroy(); + requiredDataFields.Reset(); + + // If alphabetical sorting, merge the result sets of all datastores + if (sortType == EAlphabetical) + { + // Merge the result sets of individual datastores alphabetically + CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iSearchResultsArr, + searchResults); + } + else + { + // Results are already sorted pattern based + filterHelper->GetResults(searchResults); + } + + // Get the sorted match sequence list + filterHelper->GetPatternsL(searchSeqs); + + PRINT1 ( _L("Number of search results = %d"), searchResults.Count() ); + + // Cleanup + for (TInt i = 0; i < iSearchResultsArr.Count(); i++) + { + iSearchResultsArr[i]->Reset(); + delete iSearchResultsArr[i]; + iSearchResultsArr[i] = NULL; + } + iSearchResultsArr.Reset(); + + CleanupStack::PopAndDestroy(); // query + delete filterHelper; + + PRINT ( _L("End CPcsAlgorithm2Helper::SearchITUL") ); + __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchITUL") ); + } + +// ---------------------------------------------------------------------------- +// CPcsAlgorithm2Helper::SearchQWERTYL +// Search function for QWERTY style +// ---------------------------------------------------------------------------- +void CPcsAlgorithm2Helper::SearchQWERTYL(const CPsSettings& aSettings, + CPsQuery& aPsQuery, TBool isSearchInGroup, + RArray& aContactsInGroup, + RPointerArray& searchResults, + RPointerArray& searchSeqs) + { + __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::SearchQWERTYL") ); + PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchQWERTYL") ); + + // te filtering helper for the required sort type + TSortType sortType = aSettings.GetSortType(); + CPcsAlgorithm2FilterHelper* filterHelper = + CPcsAlgorithm2FilterHelper::NewL(sortType); + + // Convert the query to string + TPtrC queryPtr = aPsQuery.QueryAsStringLC(); + + // Search from cache based on first character + const CPsQueryItem& firstCharItem = aPsQuery.GetItemAtL(0); + TInt numValue = keyMap->PoolIdForCharacter( firstCharItem.Character() ); + + // Reset the result set array for new search + iSearchResultsArr.ResetAndDestroy(); + + // Get the data stores + RPointerArray aDataStores; + aSettings.SearchUrisL(aDataStores); + + // Get the required display fields from the client + RArray requiredDataFields; + aSettings.DisplayFieldsL(requiredDataFields); + + // Perform search for each of the required data stores + RPointerArray elements; + + for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++) + { + + RPointerArray *temp = new (ELeave) RPointerArray (); + iSearchResultsArr.Append(temp); + + // Get the contents for this data store + TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex])); + if (arrayIndex < 0) + { + continue; + } + CPcsCache* cache = iAlgorithm->GetCache(arrayIndex); + cache->GetContactsForKeyL(numValue, elements); + + // Perform filtering + FilterResultsQwertyL(filterHelper, elements, queryPtr, + isSearchInGroup, aContactsInGroup); + + // If alphabetical sorting, get the results for this datastore + if (sortType == EAlphabetical) + { + filterHelper->GetResults(*(iSearchResultsArr[dsIndex])); + } + + elements.Reset(); + } + aDataStores.ResetAndDestroy(); + requiredDataFields.Reset(); // If alphabetical sorting, merge the result sets of all datastores if (sortType == EAlphabetical) { // Form the complete searchResults array CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iSearchResultsArr, - aSearchResults); + searchResults); } else { // Results are already sorted pattern based - filterHelper->GetResults(aSearchResults); + filterHelper->GetResults(searchResults); } // Get the sorted match sequence list - filterHelper->GetPatternsL(aSearchSeqs); - - PRINT1 ( _L("Number of search results = %d"), aSearchResults.Count() ); + filterHelper->GetPatternsL(searchSeqs); - // Cleanup - const TInt searchResultsArrCount = iSearchResultsArr.Count(); - for (TInt i = 0; i < searchResultsArrCount; i++) + PRINT1 ( _L("Number of search results = %d"), searchResults.Count() ); + + // Cleanup + for (TInt i = 0; i < iSearchResultsArr.Count(); i++) { iSearchResultsArr[i]->Reset(); + delete iSearchResultsArr[i]; + iSearchResultsArr[i] = NULL; } - iSearchResultsArr.ResetAndDestroy(); + iSearchResultsArr.Reset(); - CleanupStack::PopAndDestroy( filterHelper ); + CleanupStack::PopAndDestroy(); // query + delete filterHelper; - //__LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchSingleL") ); - - PRINT ( _L("End CPcsAlgorithm2Helper::SearchSingleL") ); + PRINT ( _L("End CPcsAlgorithm2Helper::SearchQWERTYL") ); + __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::SearchQWERTYL") ); } // ---------------------------------------------------------------------------- // CPcsAlgorithm2Helper::SearchMatchSeqL -// Function to search matching sequences in the input text +// Funciton to search matching sequences in the input text // ---------------------------------------------------------------------------- -void CPcsAlgorithm2Helper::SearchMatchSeqL(CPsQuery& aPsQuery, - const TDesC& aData, - RPointerArray& aMatchSet, - RArray& aMatchLocation ) +void CPcsAlgorithm2Helper::SearchMatchSeqL(HBufC* /*aQuery*/, TDesC& aData, + RPointerArray& /*aMatchSet*/, + CPsQuery& /*aPsQuery*/, + RArray& aMatchLocation) { PRINT ( _L("Enter CPcsAlgorithm2Helper::SearchMatchSeqL") ); - RArray matchPos; - CleanupClosePushL( matchPos ); - RArray matchLen; - CleanupClosePushL( matchLen ); - if ( iAlgorithm->FindUtilECE()->MatchRefineL( aData, aPsQuery, matchPos, matchLen, ETrue ) ) + // Convert the data into words + TLex lex(aData); + + // First word + TPtrC token = lex.NextToken(); + + TInt beg = lex.Offset() - token.Length(); // start index of match sequence + + // Search thru multiple words + while (token.Length() != 0) { - ASSERT( matchPos.Count() == matchLen.Count() ); - const TInt matchPosCount = matchPos.Count(); - for ( TInt i = 0 ; i < matchPosCount ; ++i ) - { - TPsMatchLocation tempLocation; - - // check for directionality of the text - TBool found(EFalse); - TPtrC matchingPart = aData.Mid( matchPos[i], matchLen[i] ); - TBidiText::TDirectionality dir = TBidiText::TextDirectionality(matchingPart, &found); - - tempLocation.index = matchPos[i]; - tempLocation.length = matchLen[i]; - tempLocation.direction = dir; - - // Add the match location to the data structure array - aMatchLocation.Append(tempLocation); - - // Add the matched sequence to set, not allowing duplicates - CPcsAlgorithm2Utils::AppendMatchToSeqL( aMatchSet, matchingPart ); - } + TPsMatchLocation tempLocation; + + // check for directionality of the text + TBool found(EFalse); + TBidiText::TDirectionality dir = TBidiText::TextDirectionality(token, &found); + + tempLocation.index = beg; + tempLocation.length = 0; + tempLocation.direction = dir; + + // Add the match location to the data structure array + aMatchLocation.Append(tempLocation); + + // Next word + token.Set(lex.NextToken()); + beg = lex.Offset() - token.Length(); // start index of next word } - CleanupStack::PopAndDestroy( &matchLen ); - CleanupStack::PopAndDestroy( &matchPos ); PRINT ( _L("End CPcsAlgorithm2Helper::SearchMatchSeqL") ); } // ---------------------------------------------------------------------------- -// CPcsAlgorithm2Helper::FilterResultsSingleL +// CPcsAlgorithm2::FilterResultsL // Subset search function // ---------------------------------------------------------------------------- -void CPcsAlgorithm2Helper::FilterResultsSingleL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper, - RPointerArray& aSearchSet, - CPsQuery& aSearchQuery, - TUint8 aFilteredDataMatch, - TBool aIsSearchInGroup, - const RArray& aContactsInGroup) +void CPcsAlgorithm2Helper::FilterResultsL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper, + RPointerArray& searchSet, + const TDesC& searchQuery, + TBool isSearchInGroup, + RArray& aContactsInGroup) { - PRINT ( _L("Enter CPcsAlgorithm2::FilterResultsSingleL") ); + __LATENCY_MARK ( _L("CPcsAlgorithm2Helper::FilterResultsL") ); + PRINT ( _L("Enter CPcsAlgorithm2Helper::FilterResultsL") ); - TInt maxcount = 0; - CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE(); + // Convert the search condition to numeric key string + TBuf tmpSearchQuery; + keyMap->GetNumericKeyString(searchQuery, tmpSearchQuery); + + //Holds the first char of first name of a contact + TBuf<10> firstChar; - // Assume that all the elements is aSearchSet are from the same database. - // Get firstname index and lastname index for that database. - // If both are found, then name fields are matched a bit differently compared - // to rest of the fields. - TInt fnIndex( KErrNotFound ); - TInt lnIndex( KErrNotFound ); - TBool fullNameSearch( EFalse ); - if ( aSearchSet.Count() ) + PRINT2 ( _L("Numeric Key String for %S = %S"), &searchQuery, &tmpSearchQuery ); + + // Parse thru each search set elements and filter the results + for (int index = 0; index < searchSet.Count(); index++) { - TInt dbUriId = aSearchSet[0]->GetPsData()->UriId(); - CPcsCache* cache = iAlgorithm->GetCache( dbUriId ); - fnIndex = cache->GetFirstNameIndex(); - lnIndex = cache->GetLastNameIndex(); - - // Ensure that firstname and lastname are among the fields to be searched - TUint8 fnBitmask = 1 << fnIndex; - TUint8 lnBitmask = 1 << lnIndex; - if ( (aFilteredDataMatch & fnBitmask) && - (aFilteredDataMatch & lnBitmask) ) - { - fullNameSearch = ETrue; - // Remove firstname and lastname from the set of fields to search - // so that they will not be searched twice. - aFilteredDataMatch &= ~fnBitmask; - aFilteredDataMatch &= ~lnBitmask; - } - } - - // Parse thru each search set elements and filter the results - const TInt searchSetCount = aSearchSet.Count(); - for (TInt index = 0; index < searchSetCount; index++) - { - CPcsPoolElement* poolElement = static_cast (aSearchSet[index]); + CPcsPoolElement* poolElement = static_cast (searchSet[index]); CPsData* psData = poolElement->GetPsData(); psData->ClearDataMatches(); + RPointerArray tempMatchSeq; - // Skip the contact if we are doing a group search and contact doesn't belong to the group - if ( aIsSearchInGroup && - aContactsInGroup.Find( psData->Id() ) == KErrNotFound ) + // Search thru multiple words + TBuf token; + TBuf firstName; + TBuf lastName; + lastName.Append(psData->Data(iAlgorithm->GetLastNameIndex())->Des()); + firstName.Append(psData->Data(iAlgorithm->GetFirstNameIndex())->Des()); + + CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE(); + TBool matched = 0; + + // If has Chinese word and the first name doesn't start with Chinese character, then should add a space + // before the first name, otherwise intitial letter searching will not function + if( pFindUtilEce->IsChineseWord(lastName) || pFindUtilEce->IsChineseWord(firstName)) { - continue; - } - - // Buffer for matched character sequence. Currently, we don't return - // accurate pattern but just first character from the matching point. - // Current clients don't actually use this data for anything. - TBuf<1> matchingData; - - TBool matched = EFalse; + token.Append(lastName); + if (firstName.Length()) + { + firstChar.Zero(); + firstChar.Append(firstName[0]); + if (!pFindUtilEce->IsChineseWord(firstChar) ) + { + token.Append(KSpace); + } + token.Append(firstName); + } + + if (token.Length() != 0) + { + matched = iAlgorithm->FindUtil()->Interface()-> + MatchRefineL(token, tmpSearchQuery, ECustomConverter, iAlgorithm); - // Parse thru each data field and filter the results - // ------------------------------------------------- - - // Name fields are handled separately to enable searching with query like - // "LastnameFirstname". Searching fullname by query string - // only for the pool elements matching with the firstname or lastname - if ( fullNameSearch && ( poolElement->IsDataMatch(fnIndex) || - poolElement->IsDataMatch(lnIndex) )) + if (matched) + { + psData->SetDataMatch(iAlgorithm->GetLastNameIndex()); + psData->SetDataMatch(iAlgorithm->GetFirstNameIndex()); + } + } + } + else { - HBufC* fullName = CreateNameBufLC( *psData, fnIndex, lnIndex ); + // If contact name only has western word, then should send + // "first name","last name" and "last name + first name" to FindUtil to do the search + const TInt lastnameLen = lastName.Length(); + const TInt firstnameLen = firstName.Length(); + if(lastnameLen) + { + matched = iAlgorithm->FindUtil()->Interface()-> + MatchRefineL(lastName, tmpSearchQuery, ECustomConverter, iAlgorithm); - // FindUtil can take care of matching queries like "Firstname", "Lastname", - // and "LastnameFirstname". - matched = pFindUtilEce->MatchRefineL( *fullName, aSearchQuery ); - if (matched) + if (matched) + { + psData->SetDataMatch(iAlgorithm->GetLastNameIndex()); + } + } + + if(!matched && firstnameLen) { - matchingData = fullName->Left(1); - psData->SetDataMatch( fnIndex ); - psData->SetDataMatch( lnIndex ); + matched = iAlgorithm->FindUtil()->Interface()-> + MatchRefineL(firstName, tmpSearchQuery, ECustomConverter, iAlgorithm); + + if (matched) + { + psData->SetDataMatch(iAlgorithm->GetFirstNameIndex()); + } } - CleanupStack::PopAndDestroy( fullName ); - } + token.Append(lastName); + token.Append(firstName); + if (!matched && lastnameLen && firstnameLen) + { + matched = iAlgorithm->FindUtil()->Interface()-> + MatchRefineL(token, tmpSearchQuery, ECustomConverter, iAlgorithm); - // Find from the rest of the fields if no match found so far. - // Name fields are already removed from aFilteredDataMatch if we did separate full name search. - const TInt dataElementCount = psData->DataElementCount(); - for ( TInt dataIndex = 0; dataIndex < dataElementCount && !matched ; dataIndex++ ) - { - // Filter off data fields not required in search - TUint8 bitIndex = 1 << dataIndex; - TUint8 filter = bitIndex & aFilteredDataMatch; - if ( filter == 0x0 ) - { - // Move to next data - continue; - } - - if ( poolElement->IsDataMatch(dataIndex) ) - { - TPtrC fieldData( *psData->Data(dataIndex) ); - matched = pFindUtilEce->MatchRefineL( fieldData, aSearchQuery ); if (matched) { - matchingData = fieldData.Left(1); - psData->SetDataMatch( dataIndex ); + psData->SetDataMatch(iAlgorithm->GetLastNameIndex()); + psData->SetDataMatch(iAlgorithm->GetFirstNameIndex()); } } } + if (matched) + { + // Extract matched character sequence, don't need to be accurate for Chinese variant + const TInt len = 1; + HBufC* seq = HBufC::NewLC(len); + *seq = token.Mid(0, len); + seq->Des().UpperCase(); - // Add to results if match is found - if ( matched ) + TIdentityRelation rule(Compare1); + if (tempMatchSeq.Find(seq, rule) == KErrNotFound) + { + tempMatchSeq.Append(seq); + CleanupStack::Pop(); + } + else + { + CleanupStack::PopAndDestroy(); + } + + + // Add the result + if (isSearchInGroup) + { + if (aContactsInGroup.Find(psData->Id()) != KErrNotFound) + { + aAlgorithmFilterHelper->AddL(psData, tempMatchSeq); + } + } + else + { + aAlgorithmFilterHelper->AddL(psData, tempMatchSeq); + } + } + + // Cleanup the match sequence array as + // they are stored in pattern details structure + tempMatchSeq.ResetAndDestroy(); + } + + PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsL") ); + __LATENCY_MARKEND ( _L("CPcsAlgorithm2Helper::FilterResultsL") ); + } + +// ---------------------------------------------------------------------------- +// CPcsAlgorithm2Helper::FilterResultsQwertyL +// Subset search function +// ---------------------------------------------------------------------------- +void CPcsAlgorithm2Helper::FilterResultsQwertyL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper, + RPointerArray& searchSet, + const TDesC& searchQuery,TBool isSearchInGroup, + RArray& aContactsInGroup) + { + PRINT ( _L("Enter CPcsAlgorithm2::FilterResultsQwertyL") ); + + TBuf<50> tmpSearchQuery = searchQuery; + tmpSearchQuery.LowerCase(); + + //Holds the first char of first name of a contact + TBuf<10> firstChar; + + // Parse thru each search set elements and filter the results + for (int index = 0; index < searchSet.Count(); index++) + { + CPcsPoolElement* poolElement = static_cast (searchSet[index]); + CPsData* psData = poolElement->GetPsData(); + psData->ClearDataMatches(); + RPointerArray tempMatchSeq; + + // Parse thru each data and filter the results + TBuf token; + TBuf firstName; + TBuf lastName; + lastName.Append(psData->Data(iAlgorithm->GetLastNameIndex())->Des()); + firstName.Append(psData->Data(iAlgorithm->GetFirstNameIndex())->Des()); + + CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE(); + TBool matched = 0; + + // If has Chinese word and the first name doesn't start with Chinese character, then should add a space + // before the first name, otherwise intitial letter searching will not function + if( pFindUtilEce->IsChineseWord(lastName) || pFindUtilEce->IsChineseWord(firstName)) { - RPointerArray tempMatchSeq; - CleanupClosePushL( tempMatchSeq ); + token.Append(lastName); + if (firstName.Length()) + { + firstChar.Zero(); + firstChar.Append(firstName[0]); + if (!pFindUtilEce->IsChineseWord(firstChar) ) + { + token.Append(KSpace); + } + token.Append(firstName); + } + + if (token.Length() != 0) + { + matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(token, tmpSearchQuery); + + if (matched) + { + psData->SetDataMatch(iAlgorithm->GetLastNameIndex()); + psData->SetDataMatch(iAlgorithm->GetFirstNameIndex()); + } + } + } + else + { + // If contact name only has western word, then should send + // "first name","last name" and "last name + first name" to FindUtil to do the search + const TInt lastnameLen = lastName.Length(); + const TInt firstnameLen = firstName.Length(); + if(lastnameLen) + { + matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(lastName, tmpSearchQuery); + + if (matched) + { + psData->SetDataMatch(iAlgorithm->GetLastNameIndex()); + } + } - // Wrap matched character sequence to array. - matchingData.UpperCase(); - tempMatchSeq.AppendL(&matchingData); + if(!matched && firstnameLen) + { + matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(firstName, tmpSearchQuery); + + if (matched) + { + psData->SetDataMatch(iAlgorithm->GetFirstNameIndex()); + } + } + + token.Append(lastName); + token.Append(firstName); + if (!matched && lastnameLen && firstnameLen) + { + matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(token, tmpSearchQuery); + + if (matched) + { + psData->SetDataMatch(iAlgorithm->GetLastNameIndex()); + psData->SetDataMatch(iAlgorithm->GetFirstNameIndex()); + } + } + } + + if (matched) + { + // Extract matched character sequence, don't need to be accurate for Chinese variant + const TInt len = 1; + HBufC* seq = HBufC::NewLC(len); + *seq = token.Mid(0, len); + seq->Des().UpperCase(); + + TIdentityRelation rule(Compare1); + if (tempMatchSeq.Find(seq, rule) == KErrNotFound) + { + tempMatchSeq.Append(seq); + CleanupStack::Pop(); + } + else + { + CleanupStack::PopAndDestroy(); + } // Add the result - aAlgorithmFilterHelper->AddL( psData, tempMatchSeq ); - maxcount++; - - // Cleanup the match sequence array as - // they are stored in pattern details structure - CleanupStack::PopAndDestroy( &tempMatchSeq ); // Close - - // TODO: Match seqs could be extracted from actual - // match locations by using the other overload of - // CFindUtilChineseECE::MatchRefineL(). - // Currently, match seq data is not used by clients. + if (isSearchInGroup) + { + if (aContactsInGroup.Find(psData->Id()) != KErrNotFound) + { + aAlgorithmFilterHelper->AddL(psData, tempMatchSeq); + } + } + else + { + aAlgorithmFilterHelper->AddL(psData, tempMatchSeq); + } } - - if ( iMaxCount != -1 && maxcount > iMaxCount ) - { - return; - } + + // Cleanup the match sequence array as + // they are stored in pattern details structure + tempMatchSeq.ResetAndDestroy(); } - PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsSingleL") ); + PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsQwertyL") ); + } + +// ---------------------------------------------------------------------------- +// CPcsAlgorithm2Helper::FilterResultsMixedL +// Subset search function +// ---------------------------------------------------------------------------- +void CPcsAlgorithm2Helper::FilterResultsMixedL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper, + RPointerArray& searchSet, + CPsQuery& searchQuery, TBool isSearchInGroup, + RArray& aContactsInGroup) + { + PRINT ( _L("Enter CPcsAlgorithm2::FilterResultsMixedL") ); + + // Convert the search query to alpha numeric string + TBuf<50> tmpSearchQuery; + ExtractQueryL(searchQuery, tmpSearchQuery); + tmpSearchQuery.LowerCase(); + TBuf<10> firstChar; + + // Parse thru each search set elements and filter the results + for (int index = 0; index < searchSet.Count(); index++) + { + CPcsPoolElement* poolElement = static_cast (searchSet[index]); + CPsData* psData = poolElement->GetPsData(); + psData->ClearDataMatches(); + RPointerArray tempMatchSeq; + + // Parse thru each data and filter the results + TBuf<255> token; + TBuf firstName; + TBuf lastName; + lastName.Append(psData->Data(iAlgorithm->GetLastNameIndex())->Des()); + firstName.Append(psData->Data(iAlgorithm->GetFirstNameIndex())->Des()); + + CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE(); + TBool matched = 0; + + // If has Chinese word and the first name doesn't start with Chinese character, then should add a space + // before the first name, otherwise intitial letter searching will not function + if( pFindUtilEce->IsChineseWord(lastName) || pFindUtilEce->IsChineseWord(firstName)) + { + token.Append(lastName); + if (firstName.Length()) + { + firstChar.Zero(); + firstChar.Append(firstName[0]); + if (!pFindUtilEce->IsChineseWord(firstChar) ) + { + token.Append(KSpace); + } + token.Append(firstName); + } + + if (token.Length() != 0) + { + matched = pFindUtilEce->MatchRefineL(token, searchQuery); + + if (matched) + { + psData->SetDataMatch(iAlgorithm->GetLastNameIndex()); + psData->SetDataMatch(iAlgorithm->GetFirstNameIndex()); + } + } + } + else + { + // If contact name only has western word, then should send + // "first name","last name" and "last name + first name" to FindUtil to do the search + const TInt lastnameLen = lastName.Length(); + const TInt firstnameLen = firstName.Length(); + if(lastnameLen) + { + matched = pFindUtilEce->MatchRefineL(lastName, searchQuery); + + if (matched) + { + psData->SetDataMatch(iAlgorithm->GetLastNameIndex()); + } + } + + if(!matched && firstnameLen) + { + matched = pFindUtilEce->MatchRefineL(firstName, searchQuery); + + if (matched) + { + psData->SetDataMatch(iAlgorithm->GetFirstNameIndex()); + } + } + + token.Append(lastName); + token.Append(firstName); + if (!matched && lastnameLen && firstnameLen) + { + matched = pFindUtilEce->MatchRefineL(token, searchQuery); + + if (matched) + { + psData->SetDataMatch(iAlgorithm->GetLastNameIndex()); + psData->SetDataMatch(iAlgorithm->GetFirstNameIndex()); + } + } + } + + if (matched) + { + // Extract matched character sequence, don't need to be accurate for Chinese variant + const TInt len = 1; + + HBufC* seq = HBufC::NewLC(len); + *seq = token.Mid(0, len); + seq->Des().UpperCase(); + + TIdentityRelation rule(Compare1); + if (tempMatchSeq.Find(seq, rule) == KErrNotFound) + { + tempMatchSeq.Append(seq); + CleanupStack::Pop(); + } + else + { + CleanupStack::PopAndDestroy(); + } + + // Add the result + if (isSearchInGroup) + { + if (aContactsInGroup.Find(psData->Id()) != KErrNotFound) + { + aAlgorithmFilterHelper->AddL(psData, tempMatchSeq); + } + } + else + { + aAlgorithmFilterHelper->AddL(psData, tempMatchSeq); + } + } + + // Cleanup the match sequence array as + // they are stored in pattern details structure + tempMatchSeq.ResetAndDestroy(); + } + + PRINT ( _L("End CPcsAlgorithm2Helper::FilterResultsMixedL") ); } // ---------------------------------------------------------------------------- @@ -419,156 +899,93 @@ void CPcsAlgorithm2Helper::SortSearchSeqsL(RPointerArray& aSearchSeqs) { // Sort the search seqs - TLinearOrder rule( CPcsAlgorithm2Utils::MyCompareC ); + TLinearOrder rule(Compare2); aSearchSeqs.Sort(rule); } -// --------------------------------------------------------------------------- -// CPcsAlgorithm2Helper::CreteNameBufLC -// Update name order according to Phonebook setting -// --------------------------------------------------------------------------- -HBufC* CPcsAlgorithm2Helper::CreateNameBufLC( const CPsData& aContactData, - TInt aFirstNameIndex, TInt aLastNameIndex ) const +// ---------------------------------------------------------------------------- +// CPcsAlgorithm2Helper::ExtractQueryL() +// Required for mixed mode search. +// ---------------------------------------------------------------------------- +void CPcsAlgorithm2Helper::ExtractQueryL(CPsQuery& aQuery, TDes& aOutput) { - const TDesC& firstName( *aContactData.Data(aFirstNameIndex) ); - const TDesC& lastName( *aContactData.Data(aLastNameIndex) ); - CFindUtilChineseECE* pFindUtilEce = iAlgorithm->FindUtilECE(); - HBufC* fullName = NULL; - - if ( pFindUtilEce->IsChineseWordIncluded( lastName ) || - pFindUtilEce->IsChineseWordIncluded( firstName ) ) + for (int i = 0; i < aQuery.Count(); i++) { - fullName = HBufC::NewLC( lastName.Length() + firstName.Length() + 1 ); - TPtr fullNamePtr = fullName->Des(); - - // Form the full name according the Phonebook name order setting. Typically, - // the order is always lastname-firstname in Chinese variants. However, at least - // currently it is possible to change this from Contacts app if UI language has - // been set to English. - if ( iNameOrder == ELastnameFirstname ) + if (aQuery.GetItemAtL(i).Mode() == EItut) { - fullNamePtr.Append( lastName ); - //Holds the first char of first name of a contact - TBuf<10> firstChar; - firstChar.Zero(); - - if(firstName.Length()) - { - firstChar.Append(firstName[0]); - // There is no space between LastName and FirstName in Chinese Name - // except that the firstChar of FirstName isn't Chinese character - if ( !pFindUtilEce->IsChineseWordIncluded( firstChar ) ) - { - fullNamePtr.Append( KSpace ); - } - fullNamePtr.Append( firstName ); - } + TBuf outBuf; + keyMap->GetNumericKeyString(aQuery.QueryAsStringLC(), outBuf); + aOutput.Append(outBuf[i]); + CleanupStack::PopAndDestroy(); } else { - fullNamePtr.Append( firstName ); - //Holds the first char of last name of a contact - TBuf<10> firstChar; - firstChar.Zero(); - - if(lastName.Length()) - { - firstChar.Append(lastName[0]); - // There is no space between LastName and FirstName in Chinese Name - // except that the firstChar of Lastname isn't Chinese character - if ( !pFindUtilEce->IsChineseWordIncluded( firstChar ) ) - { - fullNamePtr.Append( KSpace ); - } - fullNamePtr.Append( lastName ); - } - } - } - else - { - fullName = HBufC::NewLC( lastName.Length() + firstName.Length() + 1 ); - TPtr fullNamePtr = fullName->Des(); - - // Form the full name according the Phonebook name order setting. Typically, - // the order is always lastname-firstname in Chinese variants. However, at least - // currently it is possible to change this from Contacts app if UI language has - // been set to English. - if ( iNameOrder == ELastnameFirstname ) - { - fullNamePtr.Append( lastName ); - fullNamePtr.Append( KSpace ); - fullNamePtr.Append( firstName ); - } - else - { - fullNamePtr.Append( firstName ); - fullNamePtr.Append( KSpace ); - fullNamePtr.Append( lastName ); - } - } - - return fullName; - } - -// --------------------------------------------------------------------------- -// CPcsAlgorithm2Helper::UpdateNameOrderL -// Update name order according to Phonebook setting -// --------------------------------------------------------------------------- -void CPcsAlgorithm2Helper::UpdateNameOrderL() - { - /* - * Phonebook name ordering flag, integer value, possible values: - * 0: name order Lastname Firstname - * 1: name order Firstname Lastname - * 2: name order undefined - */ - TInt nameOrderSetting; - iPbkSettings->Get( MPbkGlobalSetting::ENameOrdering, nameOrderSetting ); - - switch ( nameOrderSetting ) - { - case 0: - { - iNameOrder = ELastnameFirstname; - break; - } - case 1: - { - iNameOrder = EFirstnameLastname; - break; - } - case 2: - default: - { - // Decide name order based on UI language: lastname-firstname - // for Chinese, firstname-lastname for the rest of languages. - TLanguage uiLang = User::Language(); - if ( uiLang == ELangPrcChinese || - uiLang == ELangHongKongChinese || - uiLang == ELangTaiwanChinese ) - { - iNameOrder = ELastnameFirstname; - } - else - { - iNameOrder = EFirstnameLastname; - } + aOutput.Append(aQuery.GetItemAtL(i).Character()); } } } -// --------------------------------------------------------------------------- -// CPcsAlgorithm2Helper::SettingChangedL -// From MPbkGlobalSettingObserver -// --------------------------------------------------------------------------- -void CPcsAlgorithm2Helper::SettingChangedL( MPbkGlobalSetting::TPbkGlobalSetting aKey ) +// ---------------------------------------------------------------------------- +// CPcsAlgorithm2Helper::ExtractQueryL() +// Required for mixed mode search. +// ---------------------------------------------------------------------------- +void CPcsAlgorithm2Helper::ExtractQueryL(TDesC& aInput, CPsQuery& aQuery, TDes& aOutput) { - if ( aKey == MPbkGlobalSetting::ENameOrdering ) + TInt len = -1; + + if (aInput.Length() > aQuery.Count()) + { + len = aQuery.Count(); + } + else + { + len = aInput.Length(); + } + + for (int i = 0; i < len; i++) { - UpdateNameOrderL(); + if (aQuery.GetItemAtL(i).Mode() == EItut) + { + TBuf outBuf; + keyMap->GetNumericKeyString(aInput, outBuf); + aOutput.Append(outBuf[i]); + } + else + { + aOutput.Append(aInput[i]); + } } } +// ---------------------------------------------------------------------------- +// CPcsAlgorithm2Helper::FilterDataFieldsL() +// Constructs a bit pattern using the required/supported data fields +// For example, 6, 4 and 27 are supported fields <-- 00000111 +// 6 and 4 are required fields <-- 00000011 +// Bit pattern returned is 00000011. +// ---------------------------------------------------------------------------- +TUint8 CPcsAlgorithm2Helper::FilterDataFieldsL(RArray& aRequiredDataFields, + RArray& aSupportedDataFields) + { + TUint8 filteredMatch = 0x0; + + for (int i = 0; i < aSupportedDataFields.Count(); i++) + { + for (int j = 0; j < aRequiredDataFields.Count(); j++) + { + if (aSupportedDataFields[i] == aRequiredDataFields[j]) + { + TReal val; + Math::Pow(val, 2, i); + + filteredMatch |= (TUint8) val; + } + } + } + + return filteredMatch; + } + // End of file