predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsAlgorithm2MultiSearchHelper.cpp
changeset 0 e686773b3f54
child 21 b3431bff8c19
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/predictivesearch/PcsAlgorithm/Algorithm2/src/CPcsAlgorithm2MultiSearchHelper.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,784 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Supports initial search feature. 
+*
+*/
+
+// INCLUDES
+#include "FindUtilChineseECE.h"
+#include "CPcsAlgorithm2MultiSearchHelper.h"
+#include "CPcsAlgorithm2Utils.h"
+#include "CPcsDefs.h"
+#include <collate.h>
+#include <biditext.h>
+
+// Compare functions
+TBool Compare2(const HBufC& aFirst, const HBufC& aSecond)
+    {
+    TPtrC t1(aFirst);
+    TPtrC t2(aSecond);
+    return (t1.Length() > t2.Length());
+    }
+
+TBool Compare3(const TDesC& aFirst, const TDesC& aSecond)
+    {
+    return aFirst == aSecond;
+    }
+
+TBool Compare4(const CPsQuery& aFirst, const CPsQuery& aSecond)
+    {
+    CPsQuery& first = const_cast<CPsQuery&> (aFirst);
+    CPsQuery& second = const_cast<CPsQuery&> (aSecond);
+    
+    return (first.Count() > second.Count());
+    }
+// ============================== MEMBER FUNCTIONS ============================
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::NewL
+// Two Phase Construction
+// ----------------------------------------------------------------------------
+CPcsAlgorithm2MultiSearchHelper* CPcsAlgorithm2MultiSearchHelper::NewL(CPcsAlgorithm2* aAlgorithm)
+    {
+    PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::NewL") );
+
+    CPcsAlgorithm2MultiSearchHelper* self = new (ELeave) CPcsAlgorithm2MultiSearchHelper();
+    CleanupStack::PushL(self);
+    self->ConstructL(aAlgorithm);
+    CleanupStack::Pop(self);
+
+    PRINT ( _L("End CPcsAlgorithm2MultiSearchHelper::NewL") );
+
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::CPcsAlgorithm2MultiSearchHelper
+// Two Phase Construction
+// ----------------------------------------------------------------------------
+CPcsAlgorithm2MultiSearchHelper::CPcsAlgorithm2MultiSearchHelper()
+    {
+    PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::CPcsAlgorithm2") );
+    PRINT ( _L("End CPcsAlgorithm2MultiSearchHelper::CPcsAlgorithm2") );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::ConstructL
+// Two Phase Construction
+// ----------------------------------------------------------------------------
+void CPcsAlgorithm2MultiSearchHelper::ConstructL(CPcsAlgorithm2* aAlgorithm)
+    {
+    PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::ConstructL") );
+
+    iAlgorithm = aAlgorithm;
+    keyMap = iAlgorithm->GetKeyMap();
+
+    PRINT ( _L("End CPcsAlgorithm2MultiSearchHelper::ConstructL") );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::CPcsAlgorithm2MultiSearchHelper
+// Destructor
+// ----------------------------------------------------------------------------
+CPcsAlgorithm2MultiSearchHelper::~CPcsAlgorithm2MultiSearchHelper()
+    {
+    PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::~CPcsAlgorithm2MultiSearchHelper") );
+    iMultiSearchResultsArr.ResetAndDestroy();
+    PRINT ( _L("End CPcsAlgorithm2MultiSearchHelper::~CPcsAlgorithm2MultiSearchHelper") );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::SearchMultiL
+// Initial search feature.
+// Flow of steps in initial search is explained below.
+// (1) Extract the pool elements corresponding to one of the queries.
+// (2) Always the first query is used here.
+// (3) Get pool elements from all caches corresponding to the data stores.
+// (4) Convert each query to mode specific form.
+// (5) Parse each data element.
+// (6) Check for every search query atleast one data element matches.
+// (7) If NOT ignore the result.
+// (8) If so perform an additional check that number of data matches is
+//     atleast equal to number of search queries. This will ensure that same
+//     data element has not matched for multiple queries.
+// (9) Now include the element in the result.
+// ----------------------------------------------------------------------------
+void CPcsAlgorithm2MultiSearchHelper::SearchMultiL(const CPsSettings& aSettings, 
+                                                   RPointerArray<CPsQuery>& aPsQuery,
+                                                   TBool isSearchInGroup, 
+                                                   RArray<TInt>& aContactsInGroup, 
+                                                   RPointerArray<CPsData>& searchResults,
+                                                   RPointerArray<CPsPattern>& searchSeqs,
+                                                   TInt keyboardMode)
+    {
+    __LATENCY_MARK ( _L("CPcsAlgorithm2MultiSearchHelper::SearchMultiL") );
+    PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::SearchMultiL") );
+
+    // Create CPcsAlgorithm2FilterHelper object to be used for filtering the results
+    TSortType sortType = aSettings.GetSortType();
+    CPcsAlgorithm2FilterHelper* filterHelper = CPcsAlgorithm2FilterHelper::NewL(sortType);
+    RPointerArray<CPcsPoolElement> elements;
+
+    // Get the initial search elements using the first key of first query
+    TBuf<50> numericKeyStr;
+    TPtrC queryPtr = aPsQuery[0]->QueryAsStringLC();
+    keyMap->GetNumericKeyString(queryPtr, numericKeyStr);
+    CleanupStack::PopAndDestroy();
+
+    iMultiSearchResultsArr.ResetAndDestroy();
+
+    // Get the data stores  
+    RPointerArray<TDesC> aDataStores;
+    aSettings.SearchUrisL(aDataStores);
+
+    // Get the required display fields from the client
+    RArray<TInt> requiredDataFields;
+    aSettings.DisplayFieldsL(requiredDataFields);
+
+    // Search based on first key str
+    TInt numValue = keyMap->PoolIdForCharacter(numericKeyStr[0]);
+    // Get the elements from all the databases
+    for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++)
+        {
+        RPointerArray<CPsData> *temp = new (ELeave) RPointerArray<CPsData> ();
+        iMultiSearchResultsArr.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);
+
+        // Get the supported data fields for this data store
+        RArray<TInt> supportedDataFields;
+        cache->GetDataFields(supportedDataFields);
+
+        // Get the filtered data fields for this data store    		
+        TUint8 filteredDataMatch = FilterDataFieldsL(requiredDataFields, supportedDataFields);
+
+        // Filter the results now
+        FilterResultsMultiL(filterHelper, elements, aPsQuery, filteredDataMatch, 
+                            isSearchInGroup, aContactsInGroup, keyboardMode);
+
+        // If alphabetical sorting, get the results for this datastore               
+        if (sortType == EAlphabetical)
+            {
+            filterHelper->GetResults(*(iMultiSearchResultsArr[dsIndex]));
+            }
+
+        elements.Reset();
+        supportedDataFields.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(iMultiSearchResultsArr, searchResults);
+        }
+    else
+        {
+        // Results are already sorted patternbased
+        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 < iMultiSearchResultsArr.Count(); i++)
+        {
+        iMultiSearchResultsArr[i]->Reset();
+        delete iMultiSearchResultsArr[i];
+        iMultiSearchResultsArr[i] = NULL;
+        }
+
+    iMultiSearchResultsArr.Reset();
+    delete filterHelper;
+
+    PRINT ( _L("End CPcsAlgorithm2MultiSearchHelper::SearchMultiL") );
+    __LATENCY_MARKEND ( _L("CPcsAlgorithm2MultiSearchHelper::SearchMultiL") );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::SearchInputMultiL
+// Function to search match sequences for multi query
+// ----------------------------------------------------------------------------
+void CPcsAlgorithm2MultiSearchHelper::SearchMatchSeqMultiL(RPointerArray<CPsQuery>& aPsQuery, 
+                                                           TDesC& aData, 
+                                                           RPointerArray<TDesC>& aMatchSet,
+                                                           RArray<TPsMatchLocation>& aMatchLocation)
+    {
+    PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::SearchMatchSeqMultiL") );
+    RPointerArray<HBufC> queryList;
+    ConvertQueryToListL(aPsQuery, queryList);
+
+    RPointerArray<HBufC> tempqueryList;
+    // Remember a temporary copy of query list
+    // since we sort the queries
+    for (TInt i = 0; i < queryList.Count(); i++)
+        {
+        tempqueryList.Append(queryList[i]);
+        }
+    // To hold the match results
+    RPointerArray<TDesC> tmpMatchSet;
+    TBool isMatch = ETrue;
+    TUint32 wordMatches = 0;
+
+    // Sort the query items before we search them
+    TLinearOrder<HBufC> rule(Compare2);
+    queryList.Sort(rule);
+
+    // Check for each query atleast one data element matches
+    // Loop from the last query so that longest match is seen first
+    for (TInt queryIndex = queryList.Count() - 1; queryIndex >= 0; queryIndex--)
+        {
+        TBool queryMatch = EFalse;
+        HBufC* tmpQuery = queryList[queryIndex];
+        // Get the original query mode corresponding to this query
+        TInt modeIndex = tempqueryList.Find(tmpQuery);
+
+        TLex lex(aData);
+
+        // First word
+        TPtrC tmpData = lex.NextToken();
+
+        TInt beg = lex.Offset() - tmpData.Length(); // start index of match sequence
+
+        TInt wordIndex = -1;
+        // Search thru multiple words
+        while ((tmpData.Length() != 0) && (!queryMatch))
+            {
+            wordIndex++;
+
+            TPtr ptr = tmpQuery->Des();
+
+            // Perform two checks.
+            // 1. Ensure that the word is not matched against any previous query
+            // 2. If it is the first match to the query
+            TBool isWordMatch = EFalse;
+            TReal val;
+            Math::Pow(val, 2, wordIndex);
+            isWordMatch = wordMatches & (TUint) val;
+
+            if (!isWordMatch)
+                {
+                // Check if no word is matched till now for this query
+                if (!queryMatch)
+                    {
+                    queryMatch = ETrue;
+                    //set the word match bit
+                    TReal val;
+                    Math::Pow(val, 2, wordIndex);
+                    wordMatches |= (TUint) val;
+                    }
+
+                TPsMatchLocation tempLocation;
+                // check for directionality of the text
+                TBool found(EFalse);
+                TBidiText::TDirectionality dir = TBidiText::TextDirectionality(tmpData, &found);
+
+                tempLocation.index = beg;
+                tempLocation.length = 0;
+                tempLocation.direction = dir;
+
+                // Add the match location to the data structure array
+                aMatchLocation.Append(tempLocation);
+                }
+            }
+        // Next word
+        tmpData.Set(lex.NextToken());
+        beg = lex.Offset() - tmpData.Length(); // start index of next word  
+
+
+        // No data element matches the query. Ignore this result.
+        if (queryMatch == EFalse)
+            {
+            isMatch = EFalse;
+            break;
+            }
+        }
+
+    // Count the number of bits set
+    TInt matchCount = 0;
+    matchCount = BitsSet32(wordMatches);
+
+    // If match add the element to the result set
+    // Before adding to the result set, check if there is atleast one match per query
+    // Number of bits set in word matches is atleast equal to total number of queries.
+    if ((isMatch) && (matchCount >= queryList.Count()))
+        {
+
+        // Include the match sequences in the final results
+        for (int i = 0; i < tmpMatchSet.Count(); i++)
+            {
+            TIdentityRelation<TDesC> rule(Compare3);
+            CleanupStack::PushL(tmpMatchSet[i]);
+            if (aMatchSet.Find(tmpMatchSet[i], rule) == KErrNotFound)
+                {
+                aMatchSet.Append(tmpMatchSet[i]);
+                CleanupStack::Pop();
+                }
+            else
+                {
+                CleanupStack::PopAndDestroy();
+                }
+            }
+
+        // Reset tmp match set
+        tmpMatchSet.Reset();
+        }
+    else
+        {
+        tmpMatchSet.ResetAndDestroy();
+        }
+
+    // Free the query list
+    queryList.ResetAndDestroy();
+    tempqueryList.Reset();
+
+    PRINT ( _L("End CPcsAlgorithm2MultiSearchHelper::SearchMatchSeqMultiL") );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::ConvertQueryToList
+// Converts the multiple search queries to a list
+// ----------------------------------------------------------------------------
+void CPcsAlgorithm2MultiSearchHelper::ConvertQueryToListL(RPointerArray<CPsQuery>& aSearchQuery, 
+                                                          RPointerArray<HBufC>& aQueryList)
+    {
+    for (int queryIndex = 0; queryIndex < aSearchQuery.Count(); queryIndex++)
+        {
+        CPsQuery* query = aSearchQuery[queryIndex];
+
+        HBufC* tmpSearchQuery = HBufC::NewL(KPsQueryMaxLen);
+        TPtr ptr = tmpSearchQuery->Des();
+
+        if (query->KeyboardModeL() == EItut) // ITU
+            {
+            keyMap->GetNumericKeyString(query->QueryAsStringLC(), ptr);
+            CleanupStack::PopAndDestroy();
+            }
+        else if (query->KeyboardModeL() == EQwerty) // QWERTY
+            {
+            ptr = query->QueryAsStringLC();
+            ptr.LowerCase();
+            CleanupStack::PopAndDestroy();
+            }
+        else // UNDEFINED
+            {
+            ExtractQueryL(*query, ptr);
+            ptr.LowerCase();
+            }
+        aQueryList.Append(tmpSearchQuery);
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::ConvertdDataToKeyBoardModeL
+// Converts the input data to the key board mode specified by the query
+// ----------------------------------------------------------------------------
+void CPcsAlgorithm2MultiSearchHelper::ConvertdDataToKeyBoardModeL(CPsQuery* aQuery, 
+                                                                  TPtrC aInputData, 
+                                                                  TBuf<KPsQueryMaxLen>& aOutputData)
+    {
+    if (aQuery->KeyboardModeL() == EItut)
+        {
+        keyMap->GetNumericKeyString(aInputData, aOutputData);
+        }
+    else if (aQuery->KeyboardModeL() == EQwerty)
+        {
+        aOutputData = aInputData;
+        aOutputData.LowerCase();
+        }
+    else
+        {
+        ExtractQueryL(aInputData, *aQuery, aOutputData);
+        aOutputData.LowerCase();
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::FilterResultsMultiL
+// Subset search function. Refer the above function for more description.
+// ----------------------------------------------------------------------------
+void CPcsAlgorithm2MultiSearchHelper::FilterResultsMultiL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper, 
+                                                          RPointerArray<CPcsPoolElement>& searchSet,
+                                                          RPointerArray<CPsQuery>& searchQuery, 
+                                                          TUint8 aFilteredDataMatch,
+                                                          TBool isSearchInGroup, 
+                                                          RArray<TInt>& aContactsInGroup,
+                                                          TInt keyboardMode)
+    {
+    PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::FilterResultsMultiL") );
+
+    // Convert the individual queries to string form
+    RPointerArray<CPsQuery> mySearchQuery;
+
+    // Remember a temporary copy of query list
+    // Copy the content of searchQuery
+    for (TInt i=0; i<searchQuery.Count(); i++)
+        {
+        CPsQuery* tempQuery = CPsQuery::NewL();
+        iAlgorithm->FindUtilECE()->GetPartOfQueryL(*(searchQuery[i]), 0, 
+                                                   searchQuery[i]->Count()-1, *tempQuery);
+        mySearchQuery.Append(tempQuery);
+        }
+
+    // Sort the query items according to the length of each query 
+    TLinearOrder<CPsQuery> rule(Compare4);
+    mySearchQuery.Sort(rule);
+
+    // To hold the match results
+    RPointerArray<TDesC> tmpMatchSet;
+
+    // Parse thru each search set elements and filter the results    
+    for (int index = 0; index < searchSet.Count(); index++)
+        {
+        CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (searchSet[index]);
+        CPsData* psData = poolElement->GetPsData();
+        psData->ClearDataMatches();
+
+        TBool isMatch = ETrue;
+        TUint8 wordMatches = 0;
+
+        // Reset iWordMatches to zero 
+        ClearWordMatches();
+
+        // Check for each query atleast one data element matches
+        // Loop from the last query so that longest match is seen first
+        for (TInt queryIndex = mySearchQuery.Count() - 1; queryIndex >= 0; queryIndex--)            
+            {
+            TBool queryMatch = EFalse;
+            CPsQuery* tmpPsQuery = mySearchQuery[queryIndex];
+
+            for (TInt dataIndex = 0; dataIndex < psData->DataElementCount(); dataIndex++)
+                {
+                // Filter off data fields not required in search
+                TReal bitIndex;
+                Math::Pow(bitIndex, 2, dataIndex);
+
+                TUint8 filter = (TUint8) bitIndex & aFilteredDataMatch;
+                if (filter == 0x0)
+                    {
+                    // Move to next data
+                    continue;
+                    }
+
+                TInt wordIndex = -1;
+
+                TLex lex(psData->Data(dataIndex)->Des());
+
+                // First word
+                TPtrC tmpData = lex.NextToken();
+
+                // Search thru multiple words
+                while (tmpData.Length() != 0)
+                    {
+                    wordIndex++;
+                    
+                    TPtrC queryPtr = tmpPsQuery->QueryAsStringLC();
+                    TBool matched = EFalse;
+                    
+                    if (keyboardMode == EModeUndefined)
+                        {
+                        matched = iAlgorithm->FindUtilECE()->MatchRefineL(tmpData, *tmpPsQuery);
+                        }
+                    else if (keyboardMode == EItut)
+                        {
+                        matched = iAlgorithm->FindUtil()->Interface()->
+                                  MatchRefineL(tmpData, queryPtr, ECustomConverter, iAlgorithm);
+                        }
+                    else // Qwerty
+                        {
+                        matched = iAlgorithm->FindUtil()->Interface()->MatchRefineL(tmpData, queryPtr);
+                        
+                        }
+                    
+                    CleanupStack::PopAndDestroy(); // queryPtr
+                    
+                    // Compare the data against query
+                    if (matched)
+                        {
+                        psData->SetDataMatch(dataIndex);
+
+                        // Perform two checks.
+                        // 1. Ensure that the word is not matched against any previous query
+                        // 2. If it is the first match to the query
+                        TBool isWordMatch = IsWordMatch(dataIndex, wordIndex);
+
+                        // Check if the current word is not matched to any query
+                        if (!isWordMatch)
+                            {
+                            // Check if no word is matched for this query till now
+                            if (!queryMatch)
+                                {
+                                wordMatches++;
+                                queryMatch = ETrue;
+                                SetWordMap(dataIndex, wordIndex);
+                                }
+
+                            // Extract matched character sequence and fill in temp array
+                            TInt len = tmpPsQuery->Count();
+                            if (iAlgorithm->FindUtilECE()->IsChineseWord(tmpData))
+                                {
+                                len = 1;
+                                }
+
+                            HBufC* seq = HBufC::NewL(len);
+                            *seq = tmpData.Mid(0, len);
+
+                            seq->Des().UpperCase();
+                            TIdentityRelation<TDesC> searchRule(Compare3);
+                            if (tmpMatchSet.Find(seq, searchRule) == KErrNotFound)
+                                {
+                                tmpMatchSet.Append(seq);
+                                }
+                            else
+                                {
+                                delete seq;
+                                seq = NULL;
+                                }
+                            }
+                        }
+
+                    // Next word
+                    tmpData.Set(lex.NextToken());
+                    }
+                }
+
+            // No data element matches the query. Ignore this result.
+            if (queryMatch == EFalse)
+                {
+                isMatch = EFalse;
+                break;
+                }
+            }
+
+        // If match add the element to the result set
+        //  And before adding to the result set, check if there is atleast one match per query
+        if ((isMatch) && (wordMatches >= mySearchQuery.Count()))
+            {
+            if (isSearchInGroup)
+                {
+                if (aContactsInGroup.Find(psData->Id()) != KErrNotFound)
+                    {
+                    aAlgorithmFilterHelper->AddL(psData, tmpMatchSet);
+                    }
+                }
+            else
+                {
+                aAlgorithmFilterHelper->AddL(psData, tmpMatchSet);
+                }
+            }
+
+        // Cleanup the match sequence array as 
+        // they are stored in pattern details structure
+        tmpMatchSet.ResetAndDestroy();
+        }
+
+    mySearchQuery.Reset();
+
+    PRINT ( _L("End CPcsAlgorithm2MultiSearchHelper::FilterResultsMultiL") );
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::SetWordMap()
+// ----------------------------------------------------------------------------
+void CPcsAlgorithm2MultiSearchHelper::SetWordMap(TInt aIndex, TInt aPosition)
+    {
+    TReal val;
+    Math::Pow(val, 2, aPosition);
+
+    iWordMatches[aIndex] |= (TUint8) val;
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::IsWordMatch()
+// ----------------------------------------------------------------------------
+TBool CPcsAlgorithm2MultiSearchHelper::IsWordMatch(TInt aDataIndex, TInt aWordIndex)
+    {
+    TReal val;
+    Math::Pow(val, 2, aWordIndex);
+
+    return (iWordMatches[aDataIndex] & (TUint8) val);
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::ExtractQueryL()
+// Extracts the query as a string. If the mode of query item is ITU numeric
+// character is used. Else the character is used.
+// ----------------------------------------------------------------------------
+void CPcsAlgorithm2MultiSearchHelper::ExtractQueryL(CPsQuery& aQuery, TDes& aOutput)
+    {
+    for (int i = 0; i < aQuery.Count(); i++)
+        {
+        if (aQuery.GetItemAtL(i).Mode() == EItut)
+            {
+            TBuf<KPsQueryMaxLen> outBuf;
+            keyMap->GetNumericKeyString(aQuery.QueryAsStringLC(), outBuf);
+            aOutput.Append(outBuf[i]);
+            CleanupStack::PopAndDestroy();
+            }
+        else
+            {
+            aOutput.Append(aQuery.GetItemAtL(i).Character());
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::ExtractQueryL()
+// Converts the input data refering the modes in the query.
+// If the mode of query item is ITU numeric character is used. Else the character
+// is used.
+// ----------------------------------------------------------------------------
+void CPcsAlgorithm2MultiSearchHelper::ExtractQueryL(TDesC& aInput, CPsQuery& aQuery, TDes& aOutput)
+    {
+    TInt len = -1;
+
+    // Always loop thru the lowest length
+    if (aInput.Length() > aQuery.Count())
+        {
+        len = aQuery.Count();
+        }
+    else
+        {
+        len = aInput.Length();
+        }
+
+    for (int i = 0; i < len; i++)
+        {
+        if (aQuery.GetItemAtL(i).Mode() == EItut)
+            {
+            TBuf<KPsQueryMaxLen> outBuf;
+            keyMap->GetNumericKeyString(aInput, outBuf);
+            aOutput.Append(outBuf[i]);
+            }
+        else
+            {
+            aOutput.Append(aInput[i]);
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::BitsSet32
+// Helper funtion to count the number of bits set
+// ----------------------------------------------------------------------------
+TInt CPcsAlgorithm2MultiSearchHelper::BitsSet32(TUint32 aData)
+    {
+    TInt count = 0;
+
+    for (count = 0; aData; aData &= (aData - 1))
+        {
+        count++;
+        }
+
+    return count;
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::BitsSet32
+// Function to reset the iWordMatches
+// ----------------------------------------------------------------------------
+void CPcsAlgorithm2MultiSearchHelper::ClearWordMatches()
+    {
+    for (TInt i = 0; i < MAX_DATA_FIELDS; i++)
+        iWordMatches[i] = 0;
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::MultiQuery
+// Checks if the query object has multiple queries embedded.
+// Seperator used is a space.
+// Scans through each query character and creates a new query object on a space.
+// Consequtive spaces are skipped.
+// Returns an array of query objects.
+// ----------------------------------------------------------------------------
+RPointerArray<CPsQuery> CPcsAlgorithm2MultiSearchHelper::MultiQueryL(CPsQuery& aQuery)
+    {
+    RPointerArray<CPsQuery> query;
+
+    const TInt textLength = aQuery.Count();
+
+    for (TInt beg = 0; beg < textLength; ++beg)
+        {
+        // Skip separators before next word	                
+        if (!aQuery.GetItemAtL(beg).Character().IsSpace())
+            {
+            // Scan the end of the word
+            TInt end = beg;
+            for (; end < textLength && !aQuery.GetItemAtL(end).Character().IsSpace(); ++end)
+                {
+                }
+
+            // Create a new query object and append
+            CPsQuery* newQuery = CPsQuery::NewL();
+            for (int i = beg; i < end; i++)
+                {
+                CPsQueryItem* item = CPsQueryItem::NewL();
+                item->SetCharacter(aQuery.GetItemAtL(i).Character());
+                item->SetMode(aQuery.GetItemAtL(i).Mode());
+                newQuery->AppendL(*item);
+                }
+            query.Append(newQuery);
+
+            // Scan for next word
+            beg = end;
+            }
+        }
+
+    return query;
+    }
+
+// ----------------------------------------------------------------------------
+// CPcsAlgorithm2MultiSearchHelper::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 CPcsAlgorithm2MultiSearchHelper::FilterDataFieldsL(RArray<TInt>& aRequiredDataFields, 
+                                                          RArray<TInt>& 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
+
+