96 // data element has not matched for multiple queries. |
114 // data element has not matched for multiple queries. |
97 // (9) Now include the element in the result. |
115 // (9) Now include the element in the result. |
98 // ---------------------------------------------------------------------------- |
116 // ---------------------------------------------------------------------------- |
99 void CPcsAlgorithm2MultiSearchHelper::SearchMultiL(const CPsSettings& aSettings, |
117 void CPcsAlgorithm2MultiSearchHelper::SearchMultiL(const CPsSettings& aSettings, |
100 RPointerArray<CPsQuery>& aPsQuery, |
118 RPointerArray<CPsQuery>& aPsQuery, |
101 TBool aIsSearchInGroup, |
119 TBool isSearchInGroup, |
102 const RArray<TInt>& aContactsInGroup, |
120 RArray<TInt>& aContactsInGroup, |
103 RPointerArray<CPsData>& aSearchResults, |
121 RPointerArray<CPsData>& searchResults, |
104 RPointerArray<CPsPattern>& aSearchSeqs) |
122 RPointerArray<CPsPattern>& searchSeqs, |
105 { |
123 TInt keyboardMode) |
|
124 { |
|
125 __LATENCY_MARK ( _L("CPcsAlgorithm2MultiSearchHelper::SearchMultiL") ); |
106 PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::SearchMultiL") ); |
126 PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::SearchMultiL") ); |
107 |
127 |
108 //__LATENCY_MARK ( _L("CPcsAlgorithm2MultiSearchHelper::SearchMultiL") ); |
|
109 |
|
110 PRINTQUERYLIST ( _L("CPcsAlgorithm2MultiSearchHelper::SearchMultiL: "), aPsQuery ); |
|
111 |
|
112 iMaxCount = aSettings.MaxResults(); |
|
113 // Create CPcsAlgorithm2FilterHelper object to be used for filtering the results |
128 // Create CPcsAlgorithm2FilterHelper object to be used for filtering the results |
114 TSortType sortType = aSettings.GetSortType(); |
129 TSortType sortType = aSettings.GetSortType(); |
115 CPcsAlgorithm2FilterHelper* filterHelper = CPcsAlgorithm2FilterHelper::NewL(sortType); |
130 CPcsAlgorithm2FilterHelper* filterHelper = CPcsAlgorithm2FilterHelper::NewL(sortType); |
116 CleanupStack::PushL( filterHelper ); |
|
117 RPointerArray<CPcsPoolElement> elements; |
131 RPointerArray<CPcsPoolElement> elements; |
118 CleanupClosePushL( elements ); |
|
119 |
132 |
120 iMultiSearchResultsArr.ResetAndDestroy(); |
133 iMultiSearchResultsArr.ResetAndDestroy(); |
121 |
134 |
122 // Get the data stores |
135 // Get the data stores |
123 RPointerArray<TDesC> dataStores; |
136 RPointerArray<TDesC> aDataStores; |
124 CleanupResetAndDestroyPushL( dataStores ); |
137 aSettings.SearchUrisL(aDataStores); |
125 aSettings.SearchUrisL(dataStores); |
|
126 |
138 |
127 // Get the required display fields from the client |
139 // Get the required display fields from the client |
128 RArray<TInt> requiredDataFields; |
140 RArray<TInt> requiredDataFields; |
129 CleanupClosePushL( requiredDataFields ); |
|
130 aSettings.DisplayFieldsL(requiredDataFields); |
141 aSettings.DisplayFieldsL(requiredDataFields); |
131 |
142 |
132 // Search from cache based on first character of 1st item in query list |
143 // Search from cache based on first character |
133 const CPsQueryItem& firstCharItem = aPsQuery[0]->GetItemAtL(0); |
144 const CPsQueryItem& firstCharItem = aPsQuery[0]->GetItemAtL(0); |
134 TInt cachePoolId = iKeyMap->PoolIdForCharacter( firstCharItem.Character(), firstCharItem.Mode() ); |
145 TInt numValue = keyMap->PoolIdForCharacter( firstCharItem.Character() ); |
135 |
146 |
136 // Get the elements from all the databases |
147 // Get the elements from all the databases |
137 const TInt dataStoresCount = dataStores.Count(); |
148 for (int dsIndex = 0; dsIndex < aDataStores.Count(); dsIndex++) |
138 for (TInt dsIndex = 0; dsIndex < dataStoresCount; dsIndex++) |
|
139 { |
149 { |
140 RPointerArray<CPsData> *temp = new (ELeave) RPointerArray<CPsData> (); |
150 RPointerArray<CPsData> *temp = new (ELeave) RPointerArray<CPsData> (); |
141 iMultiSearchResultsArr.Append(temp); |
151 iMultiSearchResultsArr.Append(temp); |
142 |
152 |
143 // Get the contents for this data store |
153 // Get the contents for this data store |
144 TInt arrayIndex = iAlgorithm->GetCacheIndex(*(dataStores[dsIndex])); |
154 TInt arrayIndex = iAlgorithm->GetCacheIndex(*(aDataStores[dsIndex])); |
145 if (arrayIndex < 0) |
155 if (arrayIndex < 0) |
146 { |
156 { |
147 continue; |
157 continue; |
148 } |
158 } |
149 CPcsCache* cache = iAlgorithm->GetCache(arrayIndex); |
159 CPcsCache* cache = iAlgorithm->GetCache(arrayIndex); |
150 cache->GetContactsForKeyL(cachePoolId, elements); |
160 cache->GetContactsForKeyL(numValue, elements); |
151 |
161 |
152 // Get the supported data fields for this data store |
162 // Get the supported data fields for this data store |
153 RArray<TInt> supportedDataFields; |
163 RArray<TInt> supportedDataFields; |
154 CleanupClosePushL( supportedDataFields ); |
|
155 cache->GetDataFields(supportedDataFields); |
164 cache->GetDataFields(supportedDataFields); |
156 |
165 |
157 // Get the filtered data fields for this data store |
166 // Get the filtered data fields for this data store |
158 TUint8 filteredDataMatch = CPcsAlgorithm2Utils::FilterDataFieldsL( |
167 TUint8 filteredDataMatch = FilterDataFieldsL(requiredDataFields, supportedDataFields); |
159 requiredDataFields, supportedDataFields); |
|
160 |
168 |
161 // Filter the results now |
169 // Filter the results now |
162 FilterResultsMultiL(filterHelper, |
170 FilterResultsMultiL(filterHelper, elements, aPsQuery, filteredDataMatch, |
163 elements, |
171 isSearchInGroup, aContactsInGroup, keyboardMode); |
164 aPsQuery, |
172 |
165 filteredDataMatch, |
173 // If alphabetical sorting, get the results for this datastore |
166 aIsSearchInGroup, |
|
167 aContactsInGroup); |
|
168 |
|
169 // If alphabetical sorting, get the results for this datastore |
|
170 if (sortType == EAlphabetical) |
174 if (sortType == EAlphabetical) |
171 { |
175 { |
172 filterHelper->GetResults(*(iMultiSearchResultsArr[dsIndex])); |
176 filterHelper->GetResults(*(iMultiSearchResultsArr[dsIndex])); |
173 } |
177 } |
174 |
178 |
175 elements.Reset(); |
179 elements.Reset(); |
176 CleanupStack::PopAndDestroy( &supportedDataFields ); // Close |
180 supportedDataFields.Reset(); |
177 } |
181 } |
178 CleanupStack::PopAndDestroy( &requiredDataFields ); // Close |
182 aDataStores.ResetAndDestroy(); |
179 CleanupStack::PopAndDestroy( &dataStores ); // ResetAndDestroy |
183 requiredDataFields.Reset(); |
180 |
184 |
181 // If alphabetical sorting, merge the result sets of all datastores |
185 // If alphabetical sorting, merge the result sets of all datastores |
182 if (sortType == EAlphabetical) |
186 if (sortType == EAlphabetical) |
183 { |
187 { |
184 // Form the complete searchResults array |
188 // Form the complete searchResults array |
185 CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iMultiSearchResultsArr, |
189 CPcsAlgorithm2Utils::FormCompleteSearchResultsL(iMultiSearchResultsArr, searchResults); |
186 aSearchResults); |
|
187 } |
190 } |
188 else |
191 else |
189 { |
192 { |
190 // Results are already sorted patternbased |
193 // Results are already sorted patternbased |
191 filterHelper->GetResults(aSearchResults); |
194 filterHelper->GetResults(searchResults); |
192 } |
195 } |
193 |
196 |
194 // Get the sorted match sequence list |
197 // Get the sorted match sequence list |
195 filterHelper->GetPatternsL(aSearchSeqs); |
198 filterHelper->GetPatternsL(searchSeqs); |
196 |
199 |
197 PRINT1 ( _L("Number of search results = %d"), aSearchResults.Count() ); |
200 PRINT1 ( _L("Number of search results = %d"), searchResults.Count() ); |
198 |
201 |
199 // Cleanup |
202 // Cleanup |
200 for (TInt i = 0; i < iMultiSearchResultsArr.Count(); i++) |
203 for (TInt i = 0; i < iMultiSearchResultsArr.Count(); i++) |
201 { |
204 { |
202 iMultiSearchResultsArr[i]->Reset(); |
205 iMultiSearchResultsArr[i]->Reset(); |
203 delete iMultiSearchResultsArr[i]; |
206 delete iMultiSearchResultsArr[i]; |
204 iMultiSearchResultsArr[i] = NULL; |
207 iMultiSearchResultsArr[i] = NULL; |
205 } |
208 } |
206 |
209 |
207 iMultiSearchResultsArr.Reset(); |
210 iMultiSearchResultsArr.Reset(); |
208 CleanupStack::PopAndDestroy( &elements ); // Close |
211 delete filterHelper; |
209 CleanupStack::PopAndDestroy( filterHelper ); |
|
210 |
|
211 //__LATENCY_MARKEND ( _L("CPcsAlgorithm2MultiSearchHelper::SearchMultiL") ); |
|
212 |
212 |
213 PRINT ( _L("End CPcsAlgorithm2MultiSearchHelper::SearchMultiL") ); |
213 PRINT ( _L("End CPcsAlgorithm2MultiSearchHelper::SearchMultiL") ); |
214 } |
214 __LATENCY_MARKEND ( _L("CPcsAlgorithm2MultiSearchHelper::SearchMultiL") ); |
215 |
215 } |
216 // ---------------------------------------------------------------------------- |
216 |
217 // CPcsAlgorithm1MultiSearchHelper::SearchMatchSeqMultiL |
217 // ---------------------------------------------------------------------------- |
218 // Function adds matches, and locations based on multi query, and data |
218 // CPcsAlgorithm2MultiSearchHelper::SearchInputMultiL |
219 // Duplicate locations are allowed (as they are removed later anyway) |
219 // Function to search match sequences for multi query |
220 // Post condition locations in index order |
220 // ---------------------------------------------------------------------------- |
221 // ---------------------------------------------------------------------------- |
221 void CPcsAlgorithm2MultiSearchHelper::SearchMatchSeqMultiL(RPointerArray<CPsQuery>& aPsQuery, |
222 void CPcsAlgorithm2MultiSearchHelper::SearchMatchSeqMultiL( RPointerArray<CPsQuery>& aPsQuery, |
222 TDesC& aData, |
223 const TDesC& aData, |
223 RPointerArray<TDesC>& aMatchSet, |
224 RPointerArray<TDesC>& aMatchSeq, |
224 RArray<TPsMatchLocation>& aMatchLocation) |
225 RArray<TPsMatchLocation>& aMatchLocation ) |
|
226 { |
225 { |
227 PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::SearchMatchSeqMultiL") ); |
226 PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::SearchMatchSeqMultiL") ); |
228 |
227 CleanupResetAndDestroyPushL( aMatchSet ); |
229 TLex lex(aData); |
228 CleanupClosePushL( aMatchLocation ); |
230 while ( !lex.Eos() ) // Search thru all words |
229 |
231 { |
230 RPointerArray<HBufC> queryList; |
232 TPtrC currentWord = lex.NextToken(); // next word |
231 ConvertQueryToListL(aPsQuery, queryList); |
233 |
232 |
234 const TInt psQueryCount = aPsQuery.Count(); |
233 RPointerArray<HBufC> tempqueryList; |
235 for ( TInt queryIndex = 0; queryIndex < psQueryCount; ++queryIndex ) |
234 // Remember a temporary copy of query list |
236 { |
235 // since we sort the queries |
237 CPsQuery* currentQuery = aPsQuery[queryIndex]; |
236 for (TInt i = 0; i < queryList.Count(); i++) |
238 |
237 { |
239 RArray<TInt> matchPos; |
238 tempqueryList.Append(queryList[i]); |
240 CleanupClosePushL( matchPos ); |
239 } |
241 RArray<TInt> matchLen; |
240 // To hold the match results |
242 CleanupClosePushL( matchLen ); |
241 RPointerArray<TDesC> tmpMatchSet; |
243 |
242 TBool isMatch = ETrue; |
244 if ( iAlgorithm->FindUtilECE()->MatchRefineL( currentWord, *currentQuery, matchPos, matchLen, ETrue ) ) |
243 TUint32 wordMatches = 0; |
245 { |
244 |
246 // Some matches found. Add all of them to result array. |
245 // Sort the query items before we search them |
247 ASSERT( matchPos.Count() == matchLen.Count() ); |
246 TLinearOrder<HBufC> rule(Compare2); |
248 |
247 queryList.Sort(rule); |
249 TInt wordStartPos = lex.Offset() - currentWord.Length(); |
248 |
250 const TInt matchPosCount = matchPos.Count(); |
249 // Check for each query atleast one data element matches |
251 for ( TInt i = 0 ; i < matchPosCount; ++i ) |
250 // Loop from the last query so that longest match is seen first |
|
251 for (TInt queryIndex = queryList.Count() - 1; queryIndex >= 0; queryIndex--) |
|
252 { |
|
253 TBool queryMatch = EFalse; |
|
254 HBufC* tmpQuery = queryList[queryIndex]; |
|
255 // Get the original query mode corresponding to this query |
|
256 TInt modeIndex = tempqueryList.Find(tmpQuery); |
|
257 |
|
258 TLex lex(aData); |
|
259 |
|
260 // First word |
|
261 TPtrC tmpData = lex.NextToken(); |
|
262 |
|
263 TInt beg = lex.Offset() - tmpData.Length(); // start index of match sequence |
|
264 |
|
265 TInt wordIndex = -1; |
|
266 // Search thru multiple words |
|
267 while ((tmpData.Length() != 0) && (!queryMatch)) |
|
268 { |
|
269 wordIndex++; |
|
270 |
|
271 TPtr ptr = tmpQuery->Des(); |
|
272 |
|
273 // Perform two checks. |
|
274 // 1. Ensure that the word is not matched against any previous query |
|
275 // 2. If it is the first match to the query |
|
276 TBool isWordMatch = EFalse; |
|
277 TReal val; |
|
278 Math::Pow(val, 2, wordIndex); |
|
279 isWordMatch = wordMatches & (TUint) val; |
|
280 |
|
281 if (!isWordMatch) |
|
282 { |
|
283 // Check if no word is matched till now for this query |
|
284 if (!queryMatch) |
252 { |
285 { |
253 TPsMatchLocation newLocation = { wordStartPos + matchPos[i], matchLen[i], |
286 queryMatch = ETrue; |
254 TBidiText::TextDirectionality(currentWord) }; |
287 //set the word match bit |
255 aMatchLocation.AppendL( newLocation ); |
288 TReal val; |
256 |
289 Math::Pow(val, 2, wordIndex); |
257 TPtrC matchPart = currentWord.Mid( matchPos[i], matchLen[i] ); |
290 wordMatches |= (TUint) val; |
258 CPcsAlgorithm2Utils::AppendMatchToSeqL( aMatchSeq, matchPart ); |
|
259 } |
291 } |
260 } |
292 |
261 |
293 TPsMatchLocation tempLocation; |
262 CleanupStack::PopAndDestroy( &matchLen ); |
294 // check for directionality of the text |
263 CleanupStack::PopAndDestroy( &matchPos ); |
295 TBool found(EFalse); |
264 } |
296 TBidiText::TDirectionality dir = TBidiText::TextDirectionality(tmpData, &found); |
265 } |
297 |
|
298 tempLocation.index = beg; |
|
299 tempLocation.length = 0; |
|
300 tempLocation.direction = dir; |
|
301 |
|
302 // Add the match location to the data structure array |
|
303 aMatchLocation.Append(tempLocation); |
|
304 } |
|
305 } |
|
306 // Next word |
|
307 tmpData.Set(lex.NextToken()); |
|
308 beg = lex.Offset() - tmpData.Length(); // start index of next word |
|
309 |
|
310 |
|
311 // No data element matches the query. Ignore this result. |
|
312 if (queryMatch == EFalse) |
|
313 { |
|
314 isMatch = EFalse; |
|
315 break; |
|
316 } |
|
317 } |
|
318 |
|
319 // Count the number of bits set |
|
320 TInt matchCount = 0; |
|
321 matchCount = BitsSet32(wordMatches); |
|
322 |
|
323 // If match add the element to the result set |
|
324 // Before adding to the result set, check if there is atleast one match per query |
|
325 // Number of bits set in word matches is atleast equal to total number of queries. |
|
326 if ((isMatch) && (matchCount >= queryList.Count())) |
|
327 { |
|
328 |
|
329 // Include the match sequences in the final results |
|
330 for (int i = 0; i < tmpMatchSet.Count(); i++) |
|
331 { |
|
332 TIdentityRelation<TDesC> rule(Compare3); |
|
333 CleanupStack::PushL(tmpMatchSet[i]); |
|
334 if (aMatchSet.Find(tmpMatchSet[i], rule) == KErrNotFound) |
|
335 { |
|
336 aMatchSet.Append(tmpMatchSet[i]); |
|
337 CleanupStack::Pop(); |
|
338 } |
|
339 else |
|
340 { |
|
341 CleanupStack::PopAndDestroy(); |
|
342 } |
|
343 } |
|
344 |
|
345 // Reset tmp match set |
|
346 tmpMatchSet.Reset(); |
|
347 } |
|
348 else |
|
349 { |
|
350 tmpMatchSet.ResetAndDestroy(); |
|
351 } |
|
352 |
|
353 // Free the query list |
|
354 queryList.ResetAndDestroy(); |
|
355 tempqueryList.Reset(); |
|
356 |
|
357 CleanupStack::Pop(); |
|
358 CleanupStack::Pop( &aMatchSet ); |
266 |
359 |
267 PRINT ( _L("End CPcsAlgorithm2MultiSearchHelper::SearchMatchSeqMultiL") ); |
360 PRINT ( _L("End CPcsAlgorithm2MultiSearchHelper::SearchMatchSeqMultiL") ); |
268 } |
361 } |
269 |
362 |
270 // ---------------------------------------------------------------------------- |
363 // ---------------------------------------------------------------------------- |
271 // CPcsAlgorithm2MultiSearchHelper::LookupMatchL |
364 // CPcsAlgorithm2MultiSearchHelper::ConvertQueryToList |
272 // ---------------------------------------------------------------------------- |
365 // Converts the multiple search queries to a list |
273 void CPcsAlgorithm2MultiSearchHelper::LookupMatchL( CPsQuery& aSearchQuery, |
366 // ---------------------------------------------------------------------------- |
274 const TDesC& aData, TDes& aMatchedData ) |
367 void CPcsAlgorithm2MultiSearchHelper::ConvertQueryToListL(RPointerArray<CPsQuery>& aSearchQuery, |
275 { |
368 RPointerArray<HBufC>& aQueryList) |
276 _LIT( KSpace, " " ); |
369 { |
277 aMatchedData.Zero(); |
370 for (int queryIndex = 0; queryIndex < aSearchQuery.Count(); queryIndex++) |
278 RPointerArray<CPsQuery> queryList = MultiQueryL( aSearchQuery ); |
371 { |
279 CleanupResetAndDestroyPushL( queryList ); |
372 CPsQuery* query = aSearchQuery[queryIndex]; |
|
373 |
|
374 HBufC* tmpSearchQuery = HBufC::NewL(KPsQueryMaxLen); |
|
375 TPtr ptr = tmpSearchQuery->Des(); |
|
376 |
|
377 if (query->KeyboardModeL() == EItut) // ITU |
|
378 { |
|
379 keyMap->GetNumericKeyString(query->QueryAsStringLC(), ptr); |
|
380 CleanupStack::PopAndDestroy(); |
|
381 } |
|
382 else if (query->KeyboardModeL() == EQwerty) // QWERTY |
|
383 { |
|
384 ptr = query->QueryAsStringLC(); |
|
385 ptr.LowerCase(); |
|
386 CleanupStack::PopAndDestroy(); |
|
387 } |
|
388 else // UNDEFINED |
|
389 { |
|
390 ExtractQueryL(*query, ptr); |
|
391 ptr.LowerCase(); |
|
392 } |
|
393 aQueryList.Append(tmpSearchQuery); |
|
394 } |
|
395 } |
|
396 |
|
397 // ---------------------------------------------------------------------------- |
|
398 // CPcsAlgorithm2MultiSearchHelper::ConvertdDataToKeyBoardModeL |
|
399 // Converts the input data to the key board mode specified by the query |
|
400 // ---------------------------------------------------------------------------- |
|
401 void CPcsAlgorithm2MultiSearchHelper::ConvertdDataToKeyBoardModeL(CPsQuery* aQuery, |
|
402 TPtrC aInputData, |
|
403 TBuf<KPsQueryMaxLen>& aOutputData) |
|
404 { |
|
405 if (aQuery->KeyboardModeL() == EItut) |
|
406 { |
|
407 keyMap->GetNumericKeyString(aInputData, aOutputData); |
|
408 } |
|
409 else if (aQuery->KeyboardModeL() == EQwerty) |
|
410 { |
|
411 aOutputData = aInputData; |
|
412 aOutputData.LowerCase(); |
|
413 } |
|
414 else |
|
415 { |
|
416 ExtractQueryL(aInputData, *aQuery, aOutputData); |
|
417 aOutputData.LowerCase(); |
|
418 } |
|
419 } |
|
420 |
|
421 // ---------------------------------------------------------------------------- |
|
422 // CPcsAlgorithm2MultiSearchHelper::FilterResultsMultiL |
|
423 // Subset search function. Refer the above function for more description. |
|
424 // ---------------------------------------------------------------------------- |
|
425 void CPcsAlgorithm2MultiSearchHelper::FilterResultsMultiL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper, |
|
426 RPointerArray<CPcsPoolElement>& searchSet, |
|
427 RPointerArray<CPsQuery>& searchQuery, |
|
428 TUint8 aFilteredDataMatch, |
|
429 TBool isSearchInGroup, |
|
430 RArray<TInt>& aContactsInGroup, |
|
431 TInt keyboardMode) |
|
432 { |
|
433 PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::FilterResultsMultiL") ); |
|
434 |
280 // Convert the individual queries to string form |
435 // Convert the individual queries to string form |
281 RPointerArray<CPsQuery> mySearchQuery; |
436 RPointerArray<CPsQuery> mySearchQuery; |
282 CleanupResetAndDestroyPushL( mySearchQuery ); |
|
283 |
437 |
284 // Remember a temporary copy of query list |
438 // Remember a temporary copy of query list |
285 // Copy the content of searchQuery |
439 // Copy the content of searchQuery |
286 const TInt searchQueryCount = queryList.Count(); |
440 for (TInt i=0; i<searchQuery.Count(); i++) |
287 for (TInt i = 0; i < searchQueryCount; i++ ) |
|
288 { |
441 { |
289 CPsQuery* tempQuery = CPsQuery::NewL(); |
442 CPsQuery* tempQuery = CPsQuery::NewL(); |
290 CleanupStack::PushL( tempQuery ); |
443 iAlgorithm->FindUtilECE()->GetPartOfQueryL(*(searchQuery[i]), 0, |
291 iAlgorithm->FindUtilECE()->GetPartOfQueryL( *(queryList[i]), 0, |
444 searchQuery[i]->Count()-1, *tempQuery); |
292 queryList[i]->Count() - 1, *tempQuery ); |
445 mySearchQuery.Append(tempQuery); |
293 mySearchQuery.AppendL( tempQuery ); |
|
294 CleanupStack::Pop( tempQuery ); // ownership transferred |
|
295 } |
446 } |
296 |
447 |
297 // Sort the query items according to the length of each query |
448 // Sort the query items according to the length of each query |
298 TLinearOrder<CPsQuery> rule( CPcsAlgorithm2Utils::CompareLength ); |
449 TLinearOrder<CPsQuery> rule(Compare4); |
299 mySearchQuery.Sort( rule ); |
450 mySearchQuery.Sort(rule); |
300 |
451 |
301 // To hold the match results |
452 // To hold the match results |
302 RPointerArray<TDesC> tmpMatchSet; |
453 RPointerArray<TDesC> tmpMatchSet; |
303 CleanupResetAndDestroyPushL( tmpMatchSet ); |
454 |
304 |
455 // Parse thru each search set elements and filter the results |
305 TBool isMatch = ETrue; |
456 for (int index = 0; index < searchSet.Count(); index++) |
306 TInt wordMatches = 0; |
457 { |
307 |
458 CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (searchSet[index]); |
308 // Reset iWordMatches to zero |
|
309 ClearWordMatches(); |
|
310 |
|
311 // Check for each query atleast one data element matches |
|
312 // Loop from the last query so that longest match is seen first |
|
313 for (TInt queryIndex = mySearchQuery.Count() - 1; queryIndex >= 0; queryIndex-- ) |
|
314 { |
|
315 TBool queryMatch = EFalse; |
|
316 CPsQuery* tmpPsQuery = mySearchQuery[queryIndex]; |
|
317 |
|
318 TInt wordIndex = -1; |
|
319 TLex lex( aData ); |
|
320 |
|
321 // First word |
|
322 TPtrC tmpData = lex.NextToken(); |
|
323 |
|
324 // Search thru multiple words |
|
325 while (tmpData.Length() != 0 ) |
|
326 { |
|
327 wordIndex++; |
|
328 |
|
329 // Compare the data against query |
|
330 TBool matched = iAlgorithm->FindUtilECE()->MatchRefineL( tmpData, |
|
331 *tmpPsQuery ); |
|
332 |
|
333 if ( matched ) |
|
334 { |
|
335 // Perform two checks. |
|
336 // 1. Ensure that the word is not matched against any previous query |
|
337 // 2. If it is the first match to the query |
|
338 TBool isWordMatch = IsWordMatch( 0, wordIndex ); |
|
339 |
|
340 // Check if the current word is not matched to any query |
|
341 // For example, there is a contact named "abc a" and query is key2 |
|
342 // The key2 could match the first and second 'a'. So it is required to |
|
343 // check if the current word has aready been matched before. |
|
344 |
|
345 if ( !isWordMatch ) |
|
346 { |
|
347 // Check if no word is matched for this query till now |
|
348 if ( !queryMatch ) |
|
349 { |
|
350 wordMatches++; |
|
351 queryMatch = ETrue; |
|
352 SetWordMap( 0, wordIndex ); |
|
353 // Extract matched character sequence and fill in temp array |
|
354 TInt len = tmpPsQuery->Count(); |
|
355 if ( iAlgorithm->FindUtilECE()->IsChineseWordIncluded( |
|
356 tmpData ) ) |
|
357 { |
|
358 // A Chinese word could be matched by serveral keys |
|
359 // It is hard to know the matched query length. So set it to 1 |
|
360 // as a trick result |
|
361 len = 1; |
|
362 } |
|
363 |
|
364 TPtrC seq = tmpData.Left( len ); |
|
365 CPcsAlgorithm2Utils::AppendMatchToSeqL( tmpMatchSet, |
|
366 seq ); |
|
367 } |
|
368 } |
|
369 } |
|
370 |
|
371 // Next word |
|
372 tmpData.Set( lex.NextToken() ); |
|
373 } |
|
374 |
|
375 // No data element matches the query. Ignore this result. |
|
376 if ( queryMatch == EFalse ) |
|
377 { |
|
378 isMatch = EFalse; |
|
379 break; |
|
380 } |
|
381 } |
|
382 |
|
383 // If match add the element to the result set |
|
384 // And before adding to the result set, check if there is atleast one match per query |
|
385 if ( isMatch && wordMatches >= mySearchQuery.Count() ) |
|
386 { |
|
387 const TInt matchCount = tmpMatchSet.Count(); |
|
388 for (TInt i = 0; i < matchCount; i++ ) |
|
389 { |
|
390 aMatchedData.Append( *tmpMatchSet[i] ); |
|
391 aMatchedData.Append( KSpace ); |
|
392 } |
|
393 aMatchedData.TrimRight(); |
|
394 } |
|
395 |
|
396 CleanupStack::PopAndDestroy( &tmpMatchSet ); // ResetAndDestroy |
|
397 CleanupStack::PopAndDestroy( &mySearchQuery ); // ResetAndDestroy |
|
398 CleanupStack::PopAndDestroy( &queryList ); // ResetAndDestroy |
|
399 } |
|
400 |
|
401 // ---------------------------------------------------------------------------- |
|
402 // CPcsAlgorithm2MultiSearchHelper::FilterResultsMultiL |
|
403 // Subset search function. Refer the above function for more description. |
|
404 // ---------------------------------------------------------------------------- |
|
405 void CPcsAlgorithm2MultiSearchHelper::FilterResultsMultiL(CPcsAlgorithm2FilterHelper* aAlgorithmFilterHelper, |
|
406 RPointerArray<CPcsPoolElement>& aSearchSet, |
|
407 RPointerArray<CPsQuery>& aSearchQuery, |
|
408 TUint8 aFilteredDataMatch, |
|
409 TBool aIsSearchInGroup, |
|
410 const RArray<TInt>& aContactsInGroup) |
|
411 { |
|
412 PRINT ( _L("Enter CPcsAlgorithm2MultiSearchHelper::FilterResultsMultiL") ); |
|
413 |
|
414 //__LATENCY_MARK ( _L("CPcsAlgorithm2MultiSearchHelper::FilterResultsMultiL") ); |
|
415 |
|
416 TInt maxcount = 0; |
|
417 |
|
418 // Convert the individual queries to string form |
|
419 RPointerArray<CPsQuery> mySearchQuery; |
|
420 CleanupResetAndDestroyPushL( mySearchQuery ); |
|
421 |
|
422 // Remember a temporary copy of query list |
|
423 // Copy the content of searchQuery |
|
424 const TInt searchQueryCount = aSearchQuery.Count(); |
|
425 for (TInt i=0; i < searchQueryCount; i++) |
|
426 { |
|
427 CPsQuery* tempQuery = CPsQuery::NewL(); |
|
428 CleanupStack::PushL( tempQuery ); |
|
429 iAlgorithm->FindUtilECE()->GetPartOfQueryL( |
|
430 *(aSearchQuery[i]), 0, aSearchQuery[i]->Count()-1, *tempQuery ); |
|
431 mySearchQuery.AppendL(tempQuery); |
|
432 CleanupStack::Pop(tempQuery); // ownership transferred |
|
433 } |
|
434 |
|
435 // Sort the query items according to the length of each query |
|
436 TLinearOrder<CPsQuery> rule(CPcsAlgorithm2Utils::CompareLength); |
|
437 mySearchQuery.Sort(rule); |
|
438 |
|
439 // To hold the match results |
|
440 RPointerArray<TDesC> tmpMatchSet; |
|
441 CleanupResetAndDestroyPushL( tmpMatchSet ); |
|
442 |
|
443 // Parse thru each search set elements and filter the results |
|
444 const TInt searchSetCount = aSearchSet.Count(); |
|
445 for (TInt index = 0; index < searchSetCount; index++) |
|
446 { |
|
447 CPcsPoolElement* poolElement = static_cast<CPcsPoolElement*> (aSearchSet[index]); |
|
448 CPsData* psData = poolElement->GetPsData(); |
459 CPsData* psData = poolElement->GetPsData(); |
449 psData->ClearDataMatches(); |
460 psData->ClearDataMatches(); |
450 |
461 |
451 // Skip the contact if we are doing a group search and contact doesn't belong to the group |
|
452 if ( aIsSearchInGroup && |
|
453 aContactsInGroup.Find( psData->Id() ) == KErrNotFound ) |
|
454 { |
|
455 continue; |
|
456 } |
|
457 |
|
458 TBool isMatch = ETrue; |
462 TBool isMatch = ETrue; |
459 TInt wordMatches = 0; |
463 TUint8 wordMatches = 0; |
460 |
464 |
461 // Reset iWordMatches to zero |
465 // Reset iWordMatches to zero |
462 ClearWordMatches(); |
466 ClearWordMatches(); |
463 |
467 |
464 // Check for each query atleast one data element matches |
468 // Check for each query atleast one data element matches |
465 // Loop from the last query so that longest match is seen first |
469 // Loop from the last query so that longest match is seen first |
466 for (TInt queryIndex = mySearchQuery.Count() - 1; queryIndex >= 0; queryIndex--) |
470 for (TInt queryIndex = mySearchQuery.Count() - 1; queryIndex >= 0; queryIndex--) |
467 { |
471 { |
468 TBool queryMatch = EFalse; |
472 TBool queryMatch = EFalse; |
469 CPsQuery* tmpPsQuery = mySearchQuery[queryIndex]; |
473 CPsQuery* tmpPsQuery = mySearchQuery[queryIndex]; |
470 |
474 |
471 const TInt dataElementCount = psData->DataElementCount(); |
475 for (TInt dataIndex = 0; dataIndex < psData->DataElementCount(); dataIndex++) |
472 for (TInt dataIndex = 0; dataIndex < dataElementCount; dataIndex++) |
|
473 { |
476 { |
474 // Filter off data fields not required in search |
477 // Filter off data fields not required in search |
475 TUint8 bitIndex = 1 << dataIndex; |
478 TReal bitIndex; |
476 TUint8 filter = bitIndex & aFilteredDataMatch; |
479 Math::Pow(bitIndex, 2, dataIndex); |
477 |
480 |
478 // Omit the data fields which is not required in search |
481 TUint8 filter = (TUint8) bitIndex & aFilteredDataMatch; |
479 // or not matched with the pool element |
482 if (filter == 0x0) |
480 if ( filter == 0x0 ) |
|
481 { |
483 { |
482 // Move to next data |
484 // Move to next data |
483 continue; |
485 continue; |
484 } |
486 } |
485 |
487 |