predictivesearch/PcsAlgorithm/Algorithm1/src/CPcsAlgorithm1MultiSearchHelper.cpp
changeset 0 e686773b3f54
child 3 04ab22b956c2
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Supports initial search feature. 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDES
       
    20 #include "CPcsAlgorithm1MultiSearchHelper.h"
       
    21 #include "CPcsAlgorithm1Utils.h"
       
    22 #include "CPcsDefs.h"
       
    23 #include <collate.h>
       
    24 #include <biditext.h>
       
    25 
       
    26 // Compare functions
       
    27 TBool CompareByLength ( const HBufC& aFirst, const HBufC& aSecond )
       
    28 {
       
    29    return ( aFirst.Length() > aSecond.Length() );
       
    30 }
       
    31 
       
    32 TBool Compare3 ( const TDesC& aFirst, const TDesC& aSecond )
       
    33 {
       
    34 	return aFirst == aSecond;     
       
    35 }
       
    36 // ============================== MEMBER FUNCTIONS ============================
       
    37 
       
    38 // ----------------------------------------------------------------------------
       
    39 // CPcsAlgorithm1MultiSearchHelper::NewL
       
    40 // Two Phase Construction
       
    41 // ----------------------------------------------------------------------------
       
    42 CPcsAlgorithm1MultiSearchHelper* CPcsAlgorithm1MultiSearchHelper::NewL(CPcsAlgorithm1* aAlgorithm)
       
    43 {
       
    44     PRINT ( _L("Enter CPcsAlgorithm1MultiSearchHelper::NewL") );
       
    45     
       
    46 	CPcsAlgorithm1MultiSearchHelper* self = new ( ELeave ) CPcsAlgorithm1MultiSearchHelper();
       
    47 	CleanupStack::PushL( self );
       
    48 	self->ConstructL(aAlgorithm);
       
    49 	CleanupStack::Pop( self );
       
    50 
       
    51     PRINT ( _L("End CPcsAlgorithm1MultiSearchHelper::NewL") );
       
    52     
       
    53 	return self;
       
    54 }
       
    55 
       
    56 // ----------------------------------------------------------------------------
       
    57 // CPcsAlgorithm1MultiSearchHelper::CPcsAlgorithm1MultiSearchHelper
       
    58 // Two Phase Construction
       
    59 // ----------------------------------------------------------------------------
       
    60 CPcsAlgorithm1MultiSearchHelper::CPcsAlgorithm1MultiSearchHelper()
       
    61 {		
       
    62     PRINT ( _L("Enter CPcsAlgorithm1MultiSearchHelper::CPcsAlgorithm1") );
       
    63     PRINT ( _L("End CPcsAlgorithm1MultiSearchHelper::CPcsAlgorithm1") );
       
    64 }
       
    65 
       
    66 // ----------------------------------------------------------------------------
       
    67 // CPcsAlgorithm1MultiSearchHelper::ConstructL
       
    68 // Two Phase Construction
       
    69 // ----------------------------------------------------------------------------
       
    70 void CPcsAlgorithm1MultiSearchHelper::ConstructL(CPcsAlgorithm1* aAlgorithm)
       
    71 {
       
    72     PRINT ( _L("Enter CPcsAlgorithm1MultiSearchHelper::ConstructL") );
       
    73     
       
    74     iAlgorithm = aAlgorithm;
       
    75     iKeyMap = iAlgorithm->GetKeyMap();
       
    76     
       
    77     PRINT ( _L("End CPcsAlgorithm1MultiSearchHelper::ConstructL") );
       
    78 } 	
       
    79 	
       
    80 // ----------------------------------------------------------------------------
       
    81 // CPcsAlgorithm1MultiSearchHelper::CPcsAlgorithm1MultiSearchHelper
       
    82 // Destructor
       
    83 // ----------------------------------------------------------------------------
       
    84 CPcsAlgorithm1MultiSearchHelper::~CPcsAlgorithm1MultiSearchHelper()
       
    85 {
       
    86     PRINT ( _L("Enter CPcsAlgorithm1MultiSearchHelper::~CPcsAlgorithm1MultiSearchHelper") );        
       
    87     iMultiSearchResultsArr.ResetAndDestroy();          
       
    88     PRINT ( _L("End CPcsAlgorithm1MultiSearchHelper::~CPcsAlgorithm1MultiSearchHelper") );
       
    89 }
       
    90 
       
    91 // ----------------------------------------------------------------------------
       
    92 // CPcsAlgorithm1MultiSearchHelper::SearchMultiL
       
    93 // Initial search feature.
       
    94 // Flow of steps in initial search is explained below.
       
    95 // (1) Extract the pool elements corresponding to one of the queries.
       
    96 // (2) Always the first query is used here.
       
    97 // (3) Get pool elements from all caches corresponding to the data stores.
       
    98 // (4) Convert each query to mode specific form.
       
    99 // (5) Parse each data element.
       
   100 // (6) Check for every search query atleast one data element matches.
       
   101 // (7) If NOT ignore the result.
       
   102 // (8) If so perform an additional check that number of data matches is
       
   103 //     atleast equal to number of search queries. This will ensure that same
       
   104 //     data element has not matched for multiple queries.
       
   105 // (9) Now include the element in the result.
       
   106 // ----------------------------------------------------------------------------
       
   107 void  CPcsAlgorithm1MultiSearchHelper::SearchMultiL(const CPsSettings& aSettings,
       
   108 	                                     RPointerArray<CPsQuery>& aPsQuery,
       
   109 	                                     TBool isSearchInGroup,
       
   110 	                                     RArray<TInt>& aContactsInGroup,
       
   111 	                                     RPointerArray<CPsData>& searchResults,
       
   112 	                                     RPointerArray<CPsPattern>& searchSeqs )
       
   113 {
       
   114     PRINT ( _L("Enter CPcsAlgorithm1MultiSearchHelper::SearchMultiL") );
       
   115 
       
   116     __LATENCY_MARK ( _L("CPcsAlgorithm1MultiSearchHelper::SearchMultiL") );
       
   117    
       
   118     PRINTQUERYLIST ( _L("CPcsAlgorithm1MultiSearchHelper::SearchMultiL: "), aPsQuery );
       
   119 
       
   120     // Create CPcsAlgorithm1FilterHelper object to be used for filtering the results
       
   121 	TSortType sortType = aSettings.GetSortType();
       
   122     CPcsAlgorithm1FilterHelper* filterHelper = CPcsAlgorithm1FilterHelper::NewL(sortType);
       
   123     RPointerArray<CPcsPoolElement> elements;
       
   124     
       
   125     iMultiSearchResultsArr.ResetAndDestroy();  
       
   126     
       
   127     // Get the data stores  
       
   128     RPointerArray<TDesC> aDataStores;
       
   129     aSettings.SearchUrisL(aDataStores);
       
   130           
       
   131     // Get the required display fields from the client
       
   132     RArray<TInt> requiredDataFields;
       
   133     aSettings.DisplayFieldsL(requiredDataFields);
       
   134 
       
   135     // Search based on first character of 1st item in query list
       
   136     TInt numValue = iKeyMap->PoolIdForCharacter(aPsQuery[0]->GetItemAtL(0).Character());
       
   137 
       
   138     // Get the elements from all the databases
       
   139     for ( int dsIndex = 0; 
       
   140 			dsIndex < aDataStores.Count(); 
       
   141 			dsIndex++ )
       
   142 	{
       
   143 	    RPointerArray<CPsData> *temp = new (ELeave) RPointerArray<CPsData> ();
       
   144 	    iMultiSearchResultsArr.Append(temp);
       
   145 	    
       
   146 	    // Get the contents for this data store
       
   147 	    TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex]));					    
       
   148 		if ( arrayIndex < 0 ) continue;		
       
   149 		CPcsCache* cache = iAlgorithm->GetCache(arrayIndex);	    		   
       
   150 	    cache->GetContactsForKeyL(numValue,elements);
       
   151 		
       
   152 	    // Get the supported data fields for this data store
       
   153         RArray<TInt> supportedDataFields;
       
   154 		cache->GetDataFields(supportedDataFields);
       
   155 		
       
   156 		// Get the filtered data fields for this data store    		
       
   157 		TUint8 filteredDataMatch = FilterDataFieldsL(requiredDataFields, 
       
   158 		                                             supportedDataFields);
       
   159 
       
   160 	    // Filter the results now
       
   161 	    FilterResultsMultiL(filterHelper,
       
   162                             elements,
       
   163                             aPsQuery,
       
   164                             filteredDataMatch,
       
   165                             isSearchInGroup,
       
   166                             aContactsInGroup);	
       
   167 	    
       
   168 		// If alphabetical sorting, get the results for this datastore               
       
   169 		if ( sortType == EAlphabetical )
       
   170 		{
       
   171 			filterHelper->GetResults(*(iMultiSearchResultsArr[dsIndex]));
       
   172 		}
       
   173 		
       
   174 	    elements.Reset();
       
   175 	    supportedDataFields.Reset();
       
   176 	}
       
   177 	aDataStores.ResetAndDestroy();
       
   178     requiredDataFields.Reset(); 
       
   179 	
       
   180 	// If alphabetical sorting, merge the result sets of all datastores
       
   181   	if ( sortType == EAlphabetical )
       
   182   	{
       
   183   		// Form the complete searchResults array
       
   184     	CPcsAlgorithm1Utils::FormCompleteSearchResultsL(iMultiSearchResultsArr,
       
   185     											   	    searchResults);
       
   186   	}
       
   187   	else
       
   188   	{
       
   189   		// Results are already sorted patternbased
       
   190   		filterHelper->GetResults(searchResults);
       
   191   	}
       
   192   
       
   193   	// Get the sorted match sequence list
       
   194 	filterHelper->GetPatternsL(searchSeqs);
       
   195 	
       
   196 	PRINT1 ( _L("CPcsAlgorithm1MultiSearchHelper::SearchMultiL: Number of search results = %d"), searchResults.Count() ); 
       
   197              
       
   198 	// Cleanup             
       
   199     for(TInt i = 0; i < iMultiSearchResultsArr.Count(); i++)
       
   200     {
       
   201     	iMultiSearchResultsArr[i]->Reset();
       
   202     	delete iMultiSearchResultsArr[i];
       
   203         iMultiSearchResultsArr[i] = NULL;
       
   204     }
       
   205     
       
   206     iMultiSearchResultsArr.Reset();
       
   207     delete filterHelper;
       
   208    
       
   209     __LATENCY_MARKEND ( _L("CPcsAlgorithm1MultiSearchHelper::SearchMultiL") );
       
   210 
       
   211     PRINT ( _L("End CPcsAlgorithm1MultiSearchHelper::SearchMultiL") );
       
   212 }
       
   213 
       
   214 // ----------------------------------------------------------------------------
       
   215 // CPcsAlgorithm1MultiSearchHelper::SearchMatchSeqMultiL
       
   216 // Function adds matches, and locations based on multi query, and data
       
   217 // Duplicate locations are allowed (as they are removed later anyway)
       
   218 // Post condition locations in index order
       
   219 // ----------------------------------------------------------------------------
       
   220 void  CPcsAlgorithm1MultiSearchHelper::SearchMatchSeqMultiL(RPointerArray<CPsQuery>& aPsQuery,
       
   221                                                             const TDesC& aData,
       
   222                                                             RPointerArray<TDesC>& aMatchSeq,
       
   223                                                             RArray<TPsMatchLocation>& aMatchLocation )
       
   224 {
       
   225     PRINT ( _L("Enter CPcsAlgorithm1MultiSearchHelper::SearchMatchSeqMultiL") );
       
   226     RPointerArray<HBufC> descriptorsQueryList;
       
   227     ConvertQueryToListL(aPsQuery, descriptorsQueryList);
       
   228     TLex lex(aData);
       
   229     while ( !lex.Eos() )                                    // Search thru all words
       
   230     {
       
   231         TPtrC currentWord = lex.NextToken();                // next word
       
   232 
       
   233         TPsMatchLocation newLocation = { lex.Offset() - currentWord.Length(), //start index
       
   234                                          0,
       
   235                                          TBidiText::TextDirectionality(currentWord) };
       
   236 
       
   237         for ( TInt queryIndex = 0; queryIndex < aPsQuery.Count(); ++queryIndex )
       
   238         {
       
   239             HBufC* currentQuery = descriptorsQueryList[queryIndex];
       
   240             TBuf<KPsQueryMaxLen> convertedWord;
       
   241 
       
   242             // Convert the data to required form (mode specific)
       
   243             iKeyMap->GetMixedKeyStringForDataL(*aPsQuery[queryIndex], currentWord, convertedWord);
       
   244 
       
   245             if ( CPcsAlgorithm1Utils::MyCompareC(convertedWord.Left(currentQuery->Length()), *currentQuery) == 0 )                
       
   246             {
       
   247                 newLocation.length = currentQuery->Length();
       
   248                 aMatchLocation.AppendL( newLocation );
       
   249                 AppendMatchToSeqL( aMatchSeq, currentWord.Left(newLocation.length) );
       
   250             }
       
   251         }
       
   252     }
       
   253     descriptorsQueryList.ResetAndDestroy();
       
   254     PRINT ( _L("End CPcsAlgorithm1MultiSearchHelper::SearchMatchSeqMultiL") );
       
   255 }
       
   256 
       
   257 // ----------------------------------------------------------------------------
       
   258 // CPcsAlgorithm1MultiSearchHelper::AppendMatchToSeqL
       
   259 // ----------------------------------------------------------------------------
       
   260 void CPcsAlgorithm1MultiSearchHelper::AppendMatchToSeqL( 
       
   261         RPointerArray<TDesC>& aMatchSeq, const TDesC& aMatch  )
       
   262     {
       
   263     HBufC* seq = aMatch.AllocLC();
       
   264     seq->Des().UpperCase();
       
   265     TIdentityRelation<TDesC> rule(Compare3);
       
   266     if ( aMatchSeq.Find(seq, rule) == KErrNotFound )
       
   267         {
       
   268         aMatchSeq.Append(seq);
       
   269         CleanupStack::Pop( seq );
       
   270         }
       
   271     else 
       
   272         {
       
   273         CleanupStack::PopAndDestroy( seq );
       
   274         }
       
   275     }
       
   276 
       
   277 // ----------------------------------------------------------------------------
       
   278 // CPcsAlgorithm1MultiSearchHelper::LookupMatchL
       
   279 // ----------------------------------------------------------------------------
       
   280 void CPcsAlgorithm1MultiSearchHelper::LookupMatchL( CPsQuery& aSearchQuery,
       
   281         const TDesC& aData,
       
   282         TDes& aMatchedData )
       
   283     {
       
   284     RPointerArray<CPsQuery> queryList = MultiQueryL(aSearchQuery);
       
   285     TBuf<KPsQueryMaxLen> queryAsString = aSearchQuery.QueryAsStringLC();
       
   286     TBuf<KPsQueryMaxLen> convertedQuery;
       
   287     iKeyMap->GetMixedKeyStringForDataL( aSearchQuery, queryAsString, convertedQuery );
       
   288     
       
   289     RArray<TInt> dataWordIndexes;
       
   290     RArray<TInt> dataWordLengths;
       
   291     TLex lex( aData );
       
   292     while ( !lex.Eos() )
       
   293         {
       
   294         TPtrC currentWord = lex.NextToken();
       
   295         PRINT2( _L("idx len: %d %d"), lex.Offset() - currentWord.Length(), currentWord.Length() );
       
   296         dataWordIndexes.AppendL( lex.Offset() -  currentWord.Length() );
       
   297         dataWordLengths.AppendL( currentWord.Length() );
       
   298         }
       
   299 
       
   300     RArray<TInt> queryIndexes;
       
   301     RArray<TPtrC> convertedQueriesAsDes;
       
   302     lex.Assign( queryAsString );
       
   303     while ( !lex.Eos() )
       
   304         {
       
   305         TPtrC currentWord = lex.NextToken();
       
   306         convertedQueriesAsDes.AppendL( 
       
   307                 convertedQuery.Mid( lex.Offset() - currentWord.Length(), currentWord.Length()) );
       
   308         queryIndexes.AppendL( lex.Offset() - currentWord.Length() );
       
   309         }
       
   310     
       
   311     RPointerArray< RArray<TBool> > possibleMatches;
       
   312     for ( TInt i(0); i < queryList.Count(); ++i )
       
   313         {
       
   314         RArray<TBool>* matchesForCurrentQuery = new (ELeave) RArray<TBool>;
       
   315         possibleMatches.AppendL( matchesForCurrentQuery );
       
   316         CPsQuery* currentQuery = queryList[i];
       
   317         for ( TInt j(0); j < dataWordIndexes.Count(); j++ )
       
   318             {
       
   319             TPtrC currentDataWord = aData.Mid( dataWordIndexes[j], dataWordLengths[j] );
       
   320             RBuf convertedDataWord;
       
   321             convertedDataWord.CreateL( currentDataWord.Length() );
       
   322             CleanupClosePushL( convertedDataWord );
       
   323             iKeyMap->GetMixedKeyStringForDataL( *currentQuery, currentDataWord.Left(currentQuery->Count()), convertedDataWord );
       
   324             if ( CPcsAlgorithm1Utils::MyCompareC( convertedQueriesAsDes[i], convertedDataWord ) == 0 )
       
   325                 {
       
   326                 matchesForCurrentQuery->AppendL( ETrue );
       
   327                 }
       
   328             else
       
   329                 {
       
   330                 matchesForCurrentQuery->AppendL( EFalse );
       
   331                 }
       
   332             PRINT3( _L("CPcsAlgorithm1MultiSearchHelper::LookupMatchL: possibleMatches[%d][%d]=%d"),i,j, (*(possibleMatches[i]))[j] )
       
   333             CleanupStack::PopAndDestroy( &convertedDataWord );
       
   334             }
       
   335         }
       
   336     
       
   337     const TInt KUnapplied(-1);
       
   338     RArray<TInt> appliedMatches;
       
   339     appliedMatches.ReserveL( queryList.Count() );
       
   340     for ( TInt i(0); i < queryList.Count(); ++i )
       
   341         {
       
   342         appliedMatches.AppendL( KUnapplied );
       
   343         }
       
   344     
       
   345     //backtrack algorithm starts here to find fully applied match
       
   346     TInt currentQueryIndex(0);
       
   347     while ( currentQueryIndex < queryList.Count()   
       
   348             && currentQueryIndex >= 0 )
       
   349         {
       
   350         TInt currentDataIndex = appliedMatches[ currentQueryIndex ] + 1;
       
   351         appliedMatches[ currentQueryIndex ] = KUnapplied;
       
   352         RArray<TBool>& matchesForCurrentQuery = *(possibleMatches[currentQueryIndex]);
       
   353         TBool doBacktrack( ETrue );
       
   354         while ( currentDataIndex < dataWordIndexes.Count() )
       
   355             {
       
   356             PRINT2(_L("CPcsAlgorithm1MultiSearchHelper::LookupMatchL: matchesForCurrentQuery[%d] = %d"), 
       
   357                     currentDataIndex, matchesForCurrentQuery[ currentDataIndex ] );
       
   358             
       
   359             if ( matchesForCurrentQuery[ currentDataIndex ] 
       
   360                      && (appliedMatches.Find( currentDataIndex ) == KErrNotFound) )
       
   361                 {
       
   362                 appliedMatches[ currentQueryIndex ] = currentDataIndex;
       
   363                 doBacktrack = EFalse;
       
   364                 break;
       
   365                 }
       
   366             ++currentDataIndex;
       
   367             }
       
   368         if ( doBacktrack )
       
   369             {
       
   370             --currentQueryIndex;            
       
   371             }
       
   372         else
       
   373             {
       
   374             ++currentQueryIndex;
       
   375             }
       
   376         }
       
   377     
       
   378     if ( currentQueryIndex >= 0 ) //found
       
   379         {
       
   380         aMatchedData = queryAsString;
       
   381         for ( TInt i(0); i < appliedMatches.Count(); ++i )
       
   382             {
       
   383             TInt matchedDataIndex = appliedMatches[i];
       
   384             TPtr resultFragment = aMatchedData.MidTPtr( 
       
   385                 queryIndexes[ i ],
       
   386                 convertedQueriesAsDes[i].Length() );
       
   387             resultFragment = aData.Mid(
       
   388                     dataWordIndexes[ matchedDataIndex ],
       
   389                     convertedQueriesAsDes[i].Length() );
       
   390             }        
       
   391         }
       
   392     else
       
   393         {
       
   394         aMatchedData.Zero();
       
   395         }
       
   396     
       
   397     for ( TInt i(0); i < possibleMatches.Count(); ++i )
       
   398         {
       
   399         RArray<TBool>* pointerToDelete = possibleMatches[i];
       
   400         pointerToDelete->Close();
       
   401         delete pointerToDelete;
       
   402         }
       
   403     possibleMatches.Close();
       
   404     dataWordIndexes.Close();
       
   405     dataWordLengths.Close();
       
   406 
       
   407     queryIndexes.Close();
       
   408     convertedQueriesAsDes.Close();
       
   409     queryList.Close();
       
   410     appliedMatches.Close();
       
   411     
       
   412     CleanupStack::PopAndDestroy();  //result of queryAsStringLC
       
   413     }
       
   414 
       
   415 // ----------------------------------------------------------------------------
       
   416 // CPcsAlgorithm1MultiSearchHelper::ConvertQueryToList
       
   417 // Converts the multiple search queries to a list
       
   418 // ----------------------------------------------------------------------------
       
   419 void  CPcsAlgorithm1MultiSearchHelper::ConvertQueryToListL(RPointerArray<CPsQuery>& aSearchQuery,
       
   420                                                            RPointerArray<HBufC>& aQueryList)
       
   421 {
       
   422     PRINT ( _L("Enter CPcsAlgorithm1MultiSearchHelper::ConvertQueryToListL") );
       
   423 
       
   424     for ( int queryIndex = 0; queryIndex < aSearchQuery.Count(); queryIndex++ )
       
   425     {
       
   426         TBuf<KPsQueryMaxLen> dataWithKeys;
       
   427         iKeyMap->GetMixedKeyStringForQueryL( *aSearchQuery[queryIndex], dataWithKeys );
       
   428 
       
   429         HBufC* dWKToAppend = HBufC::NewL(KPsQueryMaxLen);
       
   430         TPtr tPtr(dWKToAppend->Des());
       
   431         tPtr.Copy(dataWithKeys);
       
   432 
       
   433         aQueryList.Append( dWKToAppend );
       
   434     }
       
   435 
       
   436     PRINT ( _L("End CPcsAlgorithm1MultiSearchHelper::ConvertQueryToListL") );
       
   437 }
       
   438 
       
   439 // ----------------------------------------------------------------------------
       
   440 // CPcsAlgorithm1MultiSearchHelper::FilterResultsMultiL
       
   441 // Subset search function. Refer the above function for more description.
       
   442 // ----------------------------------------------------------------------------
       
   443 void  CPcsAlgorithm1MultiSearchHelper::FilterResultsMultiL(
       
   444         CPcsAlgorithm1FilterHelper* aAlgorithmFilterHelper,
       
   445         RPointerArray<CPcsPoolElement>& searchSet,
       
   446         RPointerArray<CPsQuery>& searchQuery,
       
   447         TUint8 aFilteredDataMatch,
       
   448         TBool isSearchInGroup,
       
   449         RArray<TInt>& aContactsInGroup)
       
   450 {
       
   451     PRINT ( _L("Enter CPcsAlgorithm1MultiSearchHelper::FilterResultsMultiL") );
       
   452 
       
   453     __LATENCY_MARK ( _L("CPcsAlgorithm1MultiSearchHelper::FilterResultsMultiL") );
       
   454 
       
   455     // Convert the individual queries to string form
       
   456     RPointerArray<HBufC> queryList;    
       
   457     RPointerArray<HBufC> tempqueryList;   
       
   458     ConvertQueryToListL(searchQuery, queryList);
       
   459     
       
   460     // Remember a temporary copy of query list
       
   461     // since we sort the queries
       
   462 	for( TInt i = 0; i < queryList.Count(); i++)
       
   463 	{
       
   464 		tempqueryList.Append(queryList[i]);
       
   465 	}
       
   466          
       
   467 	// Sort the query items before we search them
       
   468 	TLinearOrder<HBufC> rule( CompareByLength );
       
   469 	queryList.Sort(rule);
       
   470 	
       
   471     // To hold the match results
       
   472     RPointerArray<TDesC> tmpMatchSet;  
       
   473        
       
   474     // Parse thru each search set elements and filter the results    
       
   475 	for ( int index = 0; index < searchSet.Count(); index++ )
       
   476 	{
       
   477 	    CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*>(searchSet[index]);
       
   478 		CPsData* psData = poolElement->GetPsData();
       
   479 		psData->ClearDataMatches();
       
   480 		
       
   481 		TBool isMatch = ETrue;		
       
   482 		TUint8 wordMatches = 0;
       
   483 		
       
   484 		// Reset iWordMatches to zero 
       
   485 		ClearWordMatches();
       
   486 		
       
   487 		// Check for each query atleast one data element matches
       
   488 		// Loop from the last query so that longest match is seen first
       
   489 		for ( TInt queryIndex = queryList.Count() - 1; queryIndex >= 0; queryIndex-- )
       
   490 		{
       
   491 		     TBool queryMatch = EFalse;
       
   492 		     HBufC* tmpQuery = queryList[queryIndex];
       
   493 		     // Get the original query mode corresponding to this query
       
   494 		     TInt modeIndex = tempqueryList.Find(tmpQuery);
       
   495 		     
       
   496 		     for ( TInt dataIndex = 0; dataIndex < psData->DataElementCount(); dataIndex++ )
       
   497 		     {
       
   498 		         // Filter off data fields not required in search
       
   499 		         TReal bitIndex;
       
   500 		         Math::Pow(bitIndex, 2, dataIndex);
       
   501 
       
   502                  TUint8 filter = (TUint8)bitIndex & aFilteredDataMatch;     		         
       
   503 		         if ( filter == 0x0 )
       
   504 		         {
       
   505 		            // Move to next data
       
   506 		         	continue;
       
   507 		         }
       
   508 		       			     
       
   509 		         TInt wordIndex = -1;			     
       
   510 			     
       
   511 			     TLex lex(psData->Data(dataIndex)->Des());
       
   512 			     
       
   513 			     // First word
       
   514 			     TPtrC tmpData = lex.NextToken();
       
   515 			     
       
   516 			     // Search thru multiple words
       
   517 			     while ( tmpData.Length() != 0 ) 
       
   518 			     {			      
       
   519 			         wordIndex++;			         				  
       
   520 			     	 
       
   521 			     	 TBuf<KPsQueryMaxLen> data; 
       
   522 			     	  
       
   523 			         // Convert the data to required form (mode specific)
       
   524 				     iKeyMap->GetMixedKeyStringForDataL(*searchQuery[modeIndex], tmpData, data);
       
   525 				   
       
   526 				     // Compare the data against query
       
   527                      if ( CPcsAlgorithm1Utils::MyCompareC(data.Left(tmpQuery->Length()),
       
   528                                                           *tmpQuery) == 0 )				          
       
   529 				     {
       
   530 				        psData->SetDataMatch(dataIndex);				        			        
       
   531 				        
       
   532 				        // Perform two checks.
       
   533 				        // 1. Ensure that the word is not matched against any previous query
       
   534 				        // 2. If it is the first match to the query
       
   535 				        TBool isWordMatch = IsWordMatch(dataIndex, wordIndex);				        
       
   536 				      
       
   537 				        // Check if the current word is not matched to any query
       
   538 		                if( !isWordMatch )
       
   539 		                {
       
   540 		                	// Check if no word is matched for this query till now
       
   541 							if ( !queryMatch )
       
   542 							{
       
   543 								wordMatches++;
       
   544 	                 			queryMatch = ETrue;
       
   545 	                 			SetWordMap(dataIndex, wordIndex);
       
   546 							}
       
   547 							
       
   548 					        // Extract matched character sequence and fill in temp array
       
   549 							TInt len = tmpQuery->Length();
       
   550 							HBufC* seq = HBufC::NewL(len);
       
   551 							*seq = tmpData.Mid(0, len);
       
   552 							
       
   553 							seq->Des().UpperCase();
       
   554 							TIdentityRelation<TDesC> searchRule(Compare3);
       
   555 							if ( tmpMatchSet.Find(seq, searchRule) == KErrNotFound )
       
   556 							{
       
   557 							tmpMatchSet.Append(seq);
       
   558 							}
       
   559 							else
       
   560 							    { 
       
   561 								  delete seq;
       
   562 								  seq = NULL;
       
   563 							    }
       
   564 						}	
       
   565 				     }
       
   566 				     
       
   567 				     // Next word
       
   568 				     tmpData.Set(lex.NextToken());
       
   569 			     }			     
       
   570 		     }		   
       
   571 		     
       
   572 		     // No data element matches the query. Ignore this result.
       
   573 		     if ( queryMatch == EFalse )
       
   574 		     {
       
   575 		        isMatch = EFalse;
       
   576 		     	break;
       
   577 		     }		     
       
   578 		}
       
   579 		
       
   580 		// If match add the element to the result set
       
   581 		//  And before adding to the result set, check if there is atleast one match per query
       
   582 		if (( isMatch ) && ( wordMatches >= queryList.Count()))
       
   583 		{
       
   584 			if ( isSearchInGroup )
       
   585 			{
       
   586 				if ( aContactsInGroup.Find(psData->Id()) != KErrNotFound )
       
   587 				{
       
   588 					aAlgorithmFilterHelper->AddL(psData,tmpMatchSet);
       
   589 				}
       
   590 			}
       
   591 			else 
       
   592 			{
       
   593 				aAlgorithmFilterHelper->AddL(psData,tmpMatchSet);
       
   594 			}
       
   595 	    } 
       
   596 	    
       
   597 	    // Cleanup the match sequence array as 
       
   598 		// they are stored in pattern details structure
       
   599 		tmpMatchSet.ResetAndDestroy();       
       
   600 	}
       
   601 	
       
   602 	// Free the query list
       
   603 	queryList.ResetAndDestroy();
       
   604 	tempqueryList.Reset();
       
   605 
       
   606 	__LATENCY_MARKEND ( _L("CPcsAlgorithm1MultiSearchHelper::FilterResultsMultiL") );
       
   607 
       
   608 	PRINT ( _L("End CPcsAlgorithm1MultiSearchHelper::FilterResultsMultiL") );
       
   609 }
       
   610 
       
   611 // ----------------------------------------------------------------------------
       
   612 // CPcsAlgorithm1MultiSearchHelper::SetWordMap()
       
   613 // ----------------------------------------------------------------------------
       
   614 void CPcsAlgorithm1MultiSearchHelper::SetWordMap( TInt aIndex, TInt aPosition)
       
   615 {
       
   616     TReal val;
       
   617 	Math::Pow(val, 2, aPosition);
       
   618 
       
   619 	iWordMatches[aIndex] |= (TUint8)val;
       
   620 }
       
   621 
       
   622 // ----------------------------------------------------------------------------
       
   623 // CPcsAlgorithm1MultiSearchHelper::IsWordMatch()
       
   624 // ----------------------------------------------------------------------------
       
   625 TBool CPcsAlgorithm1MultiSearchHelper::IsWordMatch(TInt aDataIndex, TInt aWordIndex)
       
   626 {
       
   627     TReal val;
       
   628 	Math::Pow(val, 2, aWordIndex);
       
   629 
       
   630 	return(iWordMatches[aDataIndex] & (TUint8)val);
       
   631 }
       
   632 
       
   633 // ----------------------------------------------------------------------------
       
   634 // CPcsAlgorithm1MultiSearchHelper::ClearWordMatches
       
   635 // Function to reset the iWordMatches
       
   636 // ----------------------------------------------------------------------------
       
   637 void CPcsAlgorithm1MultiSearchHelper::ClearWordMatches()
       
   638 {
       
   639 	for( TInt i = 0; i < MAX_DATA_FIELDS; i++)
       
   640 	{
       
   641         iWordMatches[i] = 0;
       
   642 	}
       
   643 }
       
   644 
       
   645 // ----------------------------------------------------------------------------
       
   646 // CPcsAlgorithm1MultiSearchHelper::CountMultiQueryWordsL
       
   647 
       
   648 // ----------------------------------------------------------------------------
       
   649 TInt CPcsAlgorithm1MultiSearchHelper::CountMultiQueryWordsL(CPsQuery& aQuery)
       
   650 {    
       
   651     TInt wordCount = 0;
       
   652     TBool newWord = true;
       
   653 
       
   654     for (TInt i = 0; i < aQuery.Count(); i++ )
       
   655     {
       
   656         if ( aQuery.GetItemAtL(i).Character().IsSpace() )
       
   657         {
       
   658             newWord = true;
       
   659         }
       
   660         else
       
   661         {
       
   662             if ( newWord )
       
   663             {
       
   664                 wordCount++;
       
   665                 newWord = false;
       
   666             }
       
   667         }
       
   668     }
       
   669 
       
   670     PRINT1 ( _L("CPcsAlgorithm1MultiSearchHelper::CountMultiQueryWords: Number of words in search query: %d"), wordCount );
       
   671 
       
   672     return wordCount;
       
   673 }
       
   674 
       
   675 // ----------------------------------------------------------------------------
       
   676 // CPcsAlgorithm1MultiSearchHelper::MultiQuery
       
   677 // Checks if the query object has multiple queries embedded.
       
   678 // Seperator used is a space.
       
   679 // Scans through each query character and creates a new query object on a space.
       
   680 // Consequtive spaces are skipped.
       
   681 // Returns an array of query objects.
       
   682 // ----------------------------------------------------------------------------
       
   683 RPointerArray<CPsQuery> CPcsAlgorithm1MultiSearchHelper::MultiQueryL(CPsQuery& aQuery)
       
   684 {
       
   685     RPointerArray<CPsQuery> query;
       
   686     
       
   687 	const TInt textLength = aQuery.Count();
       
   688 	
       
   689     for (TInt beg = 0; beg < textLength; beg++)
       
   690     {
       
   691         // Skip separators before next word	                
       
   692         if ( !aQuery.GetItemAtL(beg).Character().IsSpace() )
       
   693         {
       
   694             // Scan the end of the word
       
   695             TInt end = beg+1;
       
   696             while (end < textLength &&                  
       
   697                    !aQuery.GetItemAtL(end).Character().IsSpace())
       
   698             {
       
   699                 end++;
       
   700             }
       
   701             
       
   702             // Create a new query object and append
       
   703             CPsQuery* newQuery = CPsQuery::NewL();
       
   704             for (TInt i = beg; i < end; i++)
       
   705             {
       
   706                 CPsQueryItem* item = CPsQueryItem::NewL();
       
   707                 item->SetCharacter(aQuery.GetItemAtL(i).Character());
       
   708                 item->SetMode(aQuery.GetItemAtL(i).Mode());
       
   709             	newQuery->AppendL(*item);
       
   710             }
       
   711             query.Append(newQuery);
       
   712             
       
   713             // Scan for next word
       
   714             beg = end;
       
   715         }
       
   716     }
       
   717 	
       
   718 	return query;
       
   719 }
       
   720 
       
   721 // ----------------------------------------------------------------------------
       
   722 // CPcsAlgorithm1MultiSearchHelper::FilterDataFieldsL()
       
   723 // Constructs a bit pattern using the required/supported data fields
       
   724 // For example, 6, 4 and 27 are supported fields <-- 00000111
       
   725 //              6 and 4 are required fields      <-- 00000011
       
   726 // Bit pattern returned is 00000011.
       
   727 // ----------------------------------------------------------------------------
       
   728 TUint8 CPcsAlgorithm1MultiSearchHelper::FilterDataFieldsL(RArray<TInt>& aRequiredDataFields,
       
   729                                                           RArray<TInt>& aSupportedDataFields)
       
   730 {
       
   731     TUint8 filteredMatch = 0x0;
       
   732     
       
   733 	for ( int i = 0; i < aSupportedDataFields.Count(); i++ )
       
   734 	{
       
   735 		for ( int j = 0; j < aRequiredDataFields.Count(); j++ )
       
   736 		{
       
   737 			if ( aSupportedDataFields[i] == aRequiredDataFields[j] )
       
   738 			{
       
   739 				TReal val;
       
   740 			    Math::Pow(val, 2, i);
       
   741 			    
       
   742 			    filteredMatch |= (TUint8)val;	
       
   743 			}
       
   744 		}
       
   745 	}
       
   746 	
       
   747 	return filteredMatch;
       
   748 }
       
   749 
       
   750 // End of file
       
   751 
       
   752