|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @internalComponent |
|
19 @released |
|
20 */ |
|
21 |
|
22 #include "persistencelayerimpl.h" |
|
23 #include "clplcontactproperties.h" |
|
24 #include <cntfilt.h> |
|
25 #include "cntsqlprovider.h" |
|
26 #include "dbsqlconstants.h" |
|
27 #include "cntpersistenceutility.h" |
|
28 #include "CNTSTD.H" |
|
29 #include <sqldb.h> |
|
30 |
|
31 // |
|
32 // The TFindFieldFlags enumeration is duplicated in cviewiterator.h. It should |
|
33 // be refactored into a shared header if possible. |
|
34 // |
|
35 enum TFindFieldFlags |
|
36 { |
|
37 EFindInAllFields =0x00000001, |
|
38 EFindFirstName =0x00000002, |
|
39 EFindLastName =0x00000004, |
|
40 EFindCompanyName =0x00000008, |
|
41 EFindInEmailField =0x00000010, |
|
42 EFindInAnyIdentityField =0x00000020, |
|
43 EFindFirstNamePronunciation =0x00000040, |
|
44 EFindLastNamePronunciation =0x00000080, |
|
45 EFindCompanyNamePronunciation =0x00000100, |
|
46 EFindInSIPField =0x00000200 |
|
47 }; |
|
48 |
|
49 |
|
50 // Maximum number of find iterations to perform in the CPlCollection::FindL() |
|
51 // method before returning. |
|
52 const TInt KFindIterations = 16; |
|
53 |
|
54 // These flags must be in the same order as the corresponding fields in |
|
55 // RPplIdentityTable::TIdentityField. |
|
56 const TFindFieldFlags KNameFlags[] = |
|
57 { |
|
58 EFindFirstName, |
|
59 EFindLastName, |
|
60 EFindCompanyName, |
|
61 EFindFirstNamePronunciation, |
|
62 EFindLastNamePronunciation, |
|
63 EFindCompanyNamePronunciation |
|
64 }; |
|
65 |
|
66 // Collation level that ignore accents (i.e. a == ä ). |
|
67 const TInt KCollationLevel= 0; |
|
68 |
|
69 // |
|
70 // The TKeyCmpTextLength class is duplicated in ccontactprivate.cpp. It should |
|
71 // be refactored into shared code/library if possible. |
|
72 // |
|
73 NONSHARABLE_CLASS(TKeyCmpTextLength) : public TKeyArrayFix |
|
74 { |
|
75 public: |
|
76 TKeyCmpTextLength(); |
|
77 protected: |
|
78 // From TKey. |
|
79 virtual TInt Compare(TInt aLeft,TInt aRight) const; |
|
80 }; |
|
81 |
|
82 |
|
83 TKeyCmpTextLength::TKeyCmpTextLength() |
|
84 // Doesn't matter using ECmpNormal, it's ignored. |
|
85 : |
|
86 TKeyArrayFix(0,ECmpNormal,0) |
|
87 { |
|
88 } |
|
89 |
|
90 |
|
91 /** |
|
92 Compare the lengths of the words. |
|
93 */ |
|
94 TInt TKeyCmpTextLength::Compare(TInt aLeft,TInt aRight) const |
|
95 { |
|
96 TDesC* left=(*((TDesC**)At(aLeft))); |
|
97 TDesC* right=(*((TDesC**)At(aRight))); |
|
98 return right->Length()-left->Length(); |
|
99 } |
|
100 |
|
101 |
|
102 /** |
|
103 Used as a cleanup item for buffer allocation in CreateFindTextL(). |
|
104 |
|
105 @param aHBufC The buffer to be cleaned up (deleted). |
|
106 */ |
|
107 GLDEF_C void DestroyHBufC(TAny* aHBufC) |
|
108 { |
|
109 delete *STATIC_CAST(HBufC**, aHBufC); |
|
110 } |
|
111 |
|
112 |
|
113 /** |
|
114 Create the "find text", used for the SQL query on the view, from the given text. |
|
115 |
|
116 @param aText Text to turn into "find text". |
|
117 |
|
118 @return "Find text" form of the given text. |
|
119 */ |
|
120 HBufC* CreateFindTextL(const TDesC& aText) |
|
121 { |
|
122 _LIT(KApostrophe, "'"); |
|
123 TInt location = aText.Find(KApostrophe); |
|
124 |
|
125 HBufC* buf=HBufC::NewL(aText.Length()+2); |
|
126 TPtr ptr=buf->Des(); |
|
127 ptr.Zero(); |
|
128 ptr.Append('%'); |
|
129 ptr += aText; |
|
130 ptr.Append('%'); |
|
131 |
|
132 // Insert additional apostrophes if required. This is so the SQL search |
|
133 // string behaves correctly. |
|
134 if(location != KErrNotFound) |
|
135 { |
|
136 CleanupStack::PushL(buf); |
|
137 |
|
138 TPtrC rightBuf = *buf; |
|
139 HBufC* leftBuf=HBufC::NewL(0); |
|
140 CleanupStack::PushL(TCleanupItem(DestroyHBufC, &leftBuf)); |
|
141 |
|
142 // Increment location because we have added the * character. |
|
143 location++; |
|
144 |
|
145 while (location != KErrNotFound) |
|
146 { |
|
147 // Copy left hand string up to the first apostrophe into a new |
|
148 // buffer and append an apostrophe. |
|
149 leftBuf = leftBuf->ReAllocL(leftBuf->Length()+location+2); |
|
150 TPtr ptrLeftBuf = leftBuf->Des(); |
|
151 ptrLeftBuf.Append(rightBuf.Left(location+1)); |
|
152 ptrLeftBuf += (KApostrophe); |
|
153 |
|
154 // Make a copy of the right hand part. |
|
155 TInt rightLength = rightBuf.Length()-location-1; |
|
156 rightBuf.Set(rightBuf.Right(rightLength)); |
|
157 |
|
158 // Search for another apostrophe. |
|
159 location = rightBuf.Find(KApostrophe); |
|
160 } |
|
161 |
|
162 // Now append the rest of the right hand part. |
|
163 leftBuf = leftBuf->ReAllocL(leftBuf->Length()+rightBuf.Length()); |
|
164 TPtr ptrLeftBuf = leftBuf->Des(); |
|
165 ptrLeftBuf.Append(rightBuf); |
|
166 |
|
167 CleanupStack::Pop(&leftBuf); |
|
168 CleanupStack::PopAndDestroy(buf); |
|
169 |
|
170 return (leftBuf); |
|
171 } |
|
172 |
|
173 return (buf); |
|
174 } |
|
175 |
|
176 |
|
177 /** |
|
178 For the given field type UID, increase aIdentityColumnsCount if the field maps |
|
179 to one of the columns in the Identity table and add the relevant find flag. |
|
180 |
|
181 @param aUid Field type UID. |
|
182 @param aFindFlags Updated with find flag which maps to the given field type UID. |
|
183 @param aIdentityColumnsCount Incremented if the field type UID maps to a column |
|
184 in the Identity table. |
|
185 */ |
|
186 // |
|
187 // This method is duplicated in cviewiterator.cpp. It should be refactored into |
|
188 // shared code/library if possible. |
|
189 // |
|
190 void SetFindFlagsAndColumnsCount(TInt32 aUid,TInt& aFindFlags,TInt& aIdentityColumnsCount) |
|
191 { |
|
192 switch(aUid) |
|
193 { |
|
194 case KUidContactFieldGivenNameValue: |
|
195 { |
|
196 ++aIdentityColumnsCount; |
|
197 aFindFlags |= EFindFirstName; |
|
198 break; |
|
199 } |
|
200 case KUidContactFieldFamilyNameValue: |
|
201 { |
|
202 ++aIdentityColumnsCount; |
|
203 aFindFlags |= EFindLastName; |
|
204 break; |
|
205 } |
|
206 case KUidContactFieldCompanyNameValue: |
|
207 { |
|
208 ++aIdentityColumnsCount; |
|
209 aFindFlags |= EFindCompanyName; |
|
210 break; |
|
211 } |
|
212 case KUidContactFieldGivenNamePronunciationValue: |
|
213 { |
|
214 ++aIdentityColumnsCount; |
|
215 aFindFlags |= EFindFirstNamePronunciation; |
|
216 break; |
|
217 } |
|
218 case KUidContactFieldFamilyNamePronunciationValue: |
|
219 { |
|
220 ++aIdentityColumnsCount; |
|
221 aFindFlags |= EFindLastNamePronunciation; |
|
222 break; |
|
223 } |
|
224 case KUidContactFieldCompanyNamePronunciationValue: |
|
225 { |
|
226 ++aIdentityColumnsCount; |
|
227 aFindFlags |= EFindCompanyNamePronunciation; |
|
228 break; |
|
229 } |
|
230 case KUidContactFieldEMailValue: |
|
231 { |
|
232 aFindFlags |= EFindInEmailField; |
|
233 break; |
|
234 } |
|
235 case KUidContactFieldSIPIDValue: |
|
236 { |
|
237 aFindFlags |= EFindInSIPField; |
|
238 break; |
|
239 } |
|
240 case KUidContactFieldMatchAllValue: |
|
241 { |
|
242 //added to address issues raised in INC049017 |
|
243 //needed as a seperate case instead of modifying the default value because Identitys should not always be searched |
|
244 //if a valid KUid is used. e.g.: KUidContactFieldAddress. If the default value was modified and someone wanted to |
|
245 //perform an address search using Elizabeth (as in elizabeth road) contacts of that name would also be found. |
|
246 aFindFlags |= EFindInAllFields|EFindInAnyIdentityField; |
|
247 break; |
|
248 } |
|
249 default: |
|
250 aFindFlags |= EFindInAllFields; |
|
251 } |
|
252 } |
|
253 |
|
254 |
|
255 /** |
|
256 Determine if the Identity table requires to be searched for the given find |
|
257 flags. |
|
258 |
|
259 @param aFindFlags Set of find flags describing which fields will be searched. |
|
260 |
|
261 @return ETrue If one of the flags in aFindFlags maps to a column in the Identity |
|
262 table, EFalse otherwise. |
|
263 */ |
|
264 // |
|
265 // This method is duplicated in cviewiterator.cpp. It should be refactored into |
|
266 // shared code/library if possible. |
|
267 // |
|
268 TBool SearchIdentityFieldsRequired(TInt aFindFlags) |
|
269 { |
|
270 return aFindFlags & |
|
271 ( EFindInAnyIdentityField | EFindFirstName | EFindLastName | EFindCompanyName | |
|
272 EFindFirstNamePronunciation | EFindLastNamePronunciation | EFindCompanyNamePronunciation); |
|
273 } |
|
274 |
|
275 |
|
276 /** |
|
277 Determine if only the Identity table requires to be searched for the given find |
|
278 flags. |
|
279 |
|
280 @param aFindFlags Set of find flags describing which fields will be searched. |
|
281 |
|
282 @return ETrue If one of the flags in aFindFlags maps to a column in the Identity |
|
283 table and no columns in any other table, EFalse otherwise. |
|
284 */ |
|
285 // |
|
286 // This method is duplicated in cviewiterator.cpp. It should be refactored into |
|
287 // shared code/library if possible. |
|
288 // |
|
289 TBool CPlCollection::UsesIdentityFieldsOnly(TInt aFindFlags) |
|
290 { |
|
291 return (aFindFlags & (EFindFirstName | EFindLastName | EFindCompanyName | |
|
292 EFindFirstNamePronunciation |EFindLastNamePronunciation |EFindCompanyNamePronunciation) ) && |
|
293 ! (aFindFlags & (EFindInAllFields | EFindInEmailField | EFindInSIPField) ); |
|
294 } |
|
295 |
|
296 |
|
297 /** |
|
298 Update a set of find flags and an Identity table column count from the field |
|
299 type UIDs in the given field definition. |
|
300 |
|
301 @param aFindFlags Updated with those flags which map to the field type UIDs in |
|
302 aFieldDef. |
|
303 @param aIdentityColumnsCount Updated with the number of field type UIDs in |
|
304 aFieldDef which map to columns in the Identity table. |
|
305 @param aFieldDef Field definition from which to create set of find flags and |
|
306 Identity table column count. |
|
307 */ |
|
308 // |
|
309 // This method is duplicated in cviewiterator.cpp. It should be refactored into |
|
310 // shared code/library if possible. |
|
311 // |
|
312 void ConstructBitwiseFindFlags(TInt& aFindFlags,TInt& aIdentityColumnsCount,const CContactItemFieldDef* aFieldDef) |
|
313 { |
|
314 if(aFieldDef!=NULL && aFieldDef->Count()>0) |
|
315 { |
|
316 for(TInt ii = 0;ii < aFieldDef->Count();ii++) |
|
317 { |
|
318 SetFindFlagsAndColumnsCount(aFieldDef->At(ii).iUid,aFindFlags,aIdentityColumnsCount); |
|
319 } |
|
320 } |
|
321 else |
|
322 { |
|
323 aFindFlags |= EFindInAllFields|EFindInAnyIdentityField; |
|
324 } |
|
325 } |
|
326 |
|
327 |
|
328 /** |
|
329 Update a set of find flags and an Identity table column count from the field |
|
330 type UIDs in the given text definition. This can be used to tell the find |
|
331 method what tables need to be searched for a given text definition. If the text |
|
332 definition is NULL we search in all tables. |
|
333 |
|
334 @param aFindFlags Updated with those flags which map to the field type UIDs in |
|
335 aTextDef. |
|
336 @param aIdentityColumnsCount Updated with the number of field type UIDs in |
|
337 aTextDef which map to columns in the Identity table. |
|
338 @param aTextDef Text definition from which to create set of find flags and |
|
339 Identity table column count. |
|
340 */ |
|
341 // |
|
342 // This method is duplicated in cviewiterator.cpp. It should be refactored into |
|
343 // shared code/library if possible. |
|
344 // |
|
345 void CPlCollection::ConstructBitwiseFlagsFromTextDef(TInt& aFindFlags,TInt& aIdentityColumnsCount,const CContactTextDef* aTextDef) |
|
346 { |
|
347 if(aTextDef != NULL && aTextDef->Count()>0) |
|
348 { |
|
349 for(TInt ii = 0;ii < aTextDef->Count();ii++) |
|
350 { |
|
351 SetFindFlagsAndColumnsCount(aTextDef->At(ii).iFieldType.iUid,aFindFlags,aIdentityColumnsCount); |
|
352 } |
|
353 TFieldType fallback = aTextDef->FallbackField(); |
|
354 if (fallback != KUidContactFieldNone) |
|
355 SetFindFlagsAndColumnsCount(fallback.iUid,aFindFlags,aIdentityColumnsCount); |
|
356 } |
|
357 else |
|
358 { |
|
359 aFindFlags |= EFindInAllFields|EFindInAnyIdentityField; |
|
360 } |
|
361 } |
|
362 |
|
363 |
|
364 /** |
|
365 Utility method used to search a contact id in contact database. |
|
366 |
|
367 @param aReqId requested contact id to look for |
|
368 @param aId out parameter; will be filled with the actual found contact item id |
|
369 @param aContactType specifies contact type to be search |
|
370 @param aDeleted set to ETrue if a search through deleted contacts is required |
|
371 |
|
372 @return ETrue if a contact item with contact id greater or equal with aReqId exists in contact database |
|
373 EFalse otherwise |
|
374 */ |
|
375 TBool CPlCollection::SeekContactL(TContactItemId aReqId,TContactItemId& aId,TUid& aContactType, TBool& aDeleted) |
|
376 { |
|
377 TBool ret = ETrue; |
|
378 |
|
379 HBufC* selectString = HBufC::NewLC(KSelectTwoFieldsWithGreater().Length() + |
|
380 KContactId().Length() + |
|
381 KContactTypeFlags().Length() + |
|
382 KSqlContactTableName().Length() + |
|
383 KContactId().Length() + 3); |
|
384 TPtr ptrSelectString = selectString->Des(); |
|
385 ptrSelectString.Format(KSelectTwoFieldsWithGreater, &KContactId, &KContactTypeFlags, &KSqlContactTableName, &KContactId, aReqId); |
|
386 |
|
387 RSqlStatement selectStatement; |
|
388 CleanupClosePushL(selectStatement); |
|
389 |
|
390 User::LeaveIfError(selectStatement.Prepare(iContactsFile.NamedDatabase(), ptrSelectString)); |
|
391 |
|
392 const TInt idIndex = selectStatement.ColumnIndex(KContactId); |
|
393 User::LeaveIfError(idIndex); |
|
394 const TInt typeIndex = selectStatement.ColumnIndex(KContactTypeFlags); |
|
395 User::LeaveIfError(typeIndex); |
|
396 TInt err; |
|
397 if((err = selectStatement.Next()) == KSqlAtRow) |
|
398 { |
|
399 aId = selectStatement.ColumnInt(idIndex); |
|
400 TInt typeFlags = selectStatement.ColumnInt(typeIndex); |
|
401 aContactType = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags); |
|
402 TInt attr = (typeFlags & EContactAttributes_Mask) >> EContactAttributes_Shift; |
|
403 aDeleted = (attr == EContactAttrsFlags_Deleted); |
|
404 } |
|
405 else |
|
406 { |
|
407 User::LeaveIfError(err); |
|
408 ret = EFalse; |
|
409 } |
|
410 |
|
411 CleanupStack::PopAndDestroy(2, selectString); //selectStatement, selectString |
|
412 return ret; |
|
413 } |
|
414 |
|
415 /** |
|
416 CPlCollection constructor. |
|
417 |
|
418 @param aContactsFile Contacts file object from the Persistence Layer. |
|
419 */ |
|
420 CPlCollection::CPlCollection(CPplContactsFile& aContactsFile) |
|
421 : |
|
422 iContactsFile( aContactsFile ), iRSqlstatementsWorking( EFalse ) |
|
423 { |
|
424 } |
|
425 |
|
426 /** |
|
427 CPlCollection ConstructL |
|
428 */ |
|
429 void CPlCollection::ConstructL() |
|
430 { |
|
431 TCntSqlStatementType statementType(ESelect, KSqlContactTableName); |
|
432 iSelectStatement = TSqlProvider::GetSqlStatementL(statementType); |
|
433 } |
|
434 |
|
435 /** |
|
436 CPlCollection NewL |
|
437 */ |
|
438 CPlCollection* CPlCollection::NewL(CPplContactsFile& aContactsFile) |
|
439 { |
|
440 CPlCollection* self = new (ELeave) CPlCollection(aContactsFile); |
|
441 CleanupStack::PushL(self); |
|
442 self->ConstructL(); |
|
443 CleanupStack::Pop(self); |
|
444 return self; |
|
445 } |
|
446 |
|
447 |
|
448 /** |
|
449 CPlCollection destructor. |
|
450 */ |
|
451 CPlCollection::~CPlCollection() |
|
452 { |
|
453 Reset(); |
|
454 delete iSelectStatement; |
|
455 iSelectStatement = NULL; |
|
456 } |
|
457 |
|
458 |
|
459 /** |
|
460 Get the count of contacts in the Contacts table. |
|
461 |
|
462 @return Count of contacts in the Contacts table. |
|
463 */ |
|
464 TInt CPlCollection::ContactCountL() |
|
465 { |
|
466 TInt count = 0; |
|
467 |
|
468 //count contact cards |
|
469 HBufC* selectString = HBufC::NewLC(KCountTypeSelect().Length() + |
|
470 KSqlContactTableName().Length() + KContactTypeFlags().Length() + KContactTypeFlags().Length() + 6); |
|
471 TPtr ptrSelectString = selectString->Des(); |
|
472 ptrSelectString.Format(KCountTypeSelect, &KSqlContactTableName, &KContactTypeFlags, EContactType_Shift, EContactTypeFlags_ContactCard, |
|
473 &KContactTypeFlags, EContactAttributes_Shift, EContactAttrsFlags_Deleted); |
|
474 |
|
475 TSqlScalarFullSelectQuery scalarQuery(iContactsFile.NamedDatabase()); |
|
476 |
|
477 count = scalarQuery.SelectIntL(ptrSelectString); |
|
478 CleanupStack::PopAndDestroy(selectString); |
|
479 |
|
480 //count own card |
|
481 selectString = HBufC::NewLC(KCountTypeSelect().Length() + |
|
482 KSqlContactTableName().Length() + KContactTypeFlags().Length() + KContactTypeFlags().Length() + 6); |
|
483 ptrSelectString = selectString->Des(); |
|
484 ptrSelectString.Format(KCountTypeSelect, &KSqlContactTableName, &KContactTypeFlags, EContactType_Shift, EContactTypeFlags_OwnCard, |
|
485 &KContactTypeFlags, EContactAttributes_Shift, EContactAttrsFlags_Deleted); |
|
486 |
|
487 count += scalarQuery.SelectIntL(ptrSelectString); |
|
488 CleanupStack::PopAndDestroy(selectString); |
|
489 |
|
490 //count groups |
|
491 selectString = HBufC::NewLC(KCountTypeSelect().Length() + |
|
492 KSqlContactTableName().Length() + KContactTypeFlags().Length() + KContactTypeFlags().Length() + 6); |
|
493 ptrSelectString = selectString->Des(); |
|
494 ptrSelectString.Format(KCountTypeSelect, &KSqlContactTableName, &KContactTypeFlags, EContactType_Shift, EContactTypeFlags_Group, |
|
495 &KContactTypeFlags, EContactAttributes_Shift, EContactAttrsFlags_Deleted); |
|
496 |
|
497 count += scalarQuery.SelectIntL(ptrSelectString); |
|
498 CleanupStack::PopAndDestroy(selectString); |
|
499 |
|
500 //card template |
|
501 selectString = HBufC::NewLC(KCountTypeSelect().Length() + |
|
502 KSqlContactTableName().Length() + KContactTypeFlags().Length() + KContactTypeFlags().Length() + 6); |
|
503 ptrSelectString = selectString->Des(); |
|
504 ptrSelectString.Format(KCountTypeSelect, &KSqlContactTableName, &KContactTypeFlags, EContactType_Shift, EContactTypeFlags_CardTemplate, |
|
505 &KContactTypeFlags, EContactAttributes_Shift, EContactAttrsFlags_Deleted); |
|
506 |
|
507 count += scalarQuery.SelectIntL(ptrSelectString); |
|
508 CleanupStack::PopAndDestroy(selectString); |
|
509 |
|
510 return count; |
|
511 } |
|
512 |
|
513 |
|
514 /** |
|
515 Get a collection of contact IDs using the specified view/collection parameters. |
|
516 |
|
517 @param aViewType Type of view/collection. |
|
518 @param aTime Used if view/collection type is "changed since". |
|
519 @param aGuid Used if view/collection type is "find GUID". |
|
520 |
|
521 @return Contact ID array of those contacts which match the specified collection |
|
522 parameters. |
|
523 */ |
|
524 CContactIdArray* CPlCollection::CollectionL(TLplViewType aViewType,TTime aTime,const TDesC& aGuid) |
|
525 { |
|
526 CContactIdArray* idArray=NULL; |
|
527 switch(aViewType) |
|
528 { |
|
529 case EChangedSince : |
|
530 { |
|
531 idArray = ChangedSinceL(aTime); |
|
532 } |
|
533 break; |
|
534 case EDeleted : |
|
535 { |
|
536 idArray = DeletedL(); |
|
537 } |
|
538 break; |
|
539 case EUnfiled : |
|
540 { |
|
541 idArray = UnfiledL(); |
|
542 } |
|
543 break; |
|
544 case EFindGuid : |
|
545 { |
|
546 idArray = GuidL(aGuid); |
|
547 } |
|
548 break; |
|
549 default: |
|
550 { |
|
551 User::Leave(KErrNotFound); |
|
552 } |
|
553 break; |
|
554 } |
|
555 return idArray; |
|
556 } |
|
557 |
|
558 |
|
559 /** |
|
560 Utility method used to serach hint field for provided contact id |
|
561 |
|
562 @param aBitWiseFileter filter used for hint matching |
|
563 @param aContactId contact item id |
|
564 |
|
565 @return ETrue if a hint is found |
|
566 EFalse otherwise |
|
567 */ |
|
568 TBool CPlCollection::ContactMatchesHintFieldL(TInt aBitWiseFilter, TContactItemId aContactId) |
|
569 { |
|
570 TBool hintMatch = EFalse; |
|
571 |
|
572 HBufC* searchCond = HBufC::NewLC(KConditionClause().Length() + KContactId().Length() + 32); |
|
573 searchCond->Des().Format(KConditionClause, &KContactId, aContactId); |
|
574 |
|
575 RSqlStatement selectStatement; |
|
576 CleanupClosePushL(selectStatement); |
|
577 |
|
578 iSelectStatement->Reset(); |
|
579 iSelectStatement->SetParamL(KContactId, KSpace); |
|
580 iSelectStatement->SetParamL(KContactTypeFlagsParam, KSpace); |
|
581 iSelectStatement->SetConditionL(*searchCond); |
|
582 |
|
583 User::LeaveIfError(selectStatement.Prepare(iContactsFile.NamedDatabase(), iSelectStatement->SqlStringL())); |
|
584 |
|
585 TInt err; |
|
586 if((err = selectStatement.Next()) == KSqlAtRow) |
|
587 { |
|
588 const TInt typeFlagsIndex = iSelectStatement->ParameterIndex(KContactTypeFlags); |
|
589 TInt typeFlags = selectStatement.ColumnInt(typeFlagsIndex); |
|
590 TUid contactType = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags); |
|
591 if (iContactsFile.ContactProperties().CheckType(contactType)) |
|
592 { |
|
593 TInt hint = typeFlags & EContactHintFlags_Mask; |
|
594 hintMatch = HintFieldMatchesFilter(hint, aBitWiseFilter); |
|
595 } |
|
596 } |
|
597 else |
|
598 { |
|
599 User::LeaveIfError(err); |
|
600 } |
|
601 |
|
602 CleanupStack::PopAndDestroy(2, searchCond); //searchCond, selectStatement |
|
603 return hintMatch; |
|
604 } |
|
605 |
|
606 /** |
|
607 Utility method used for phone matching |
|
608 |
|
609 @param aNumber phone number to be matched |
|
610 @param aMatchLengthFromRight specifies the number of relevant characters to be matched |
|
611 @return array with contact ids matching passed phone number |
|
612 */ |
|
613 CContactIdArray* CPlCollection::MatchPhoneNumberL(const TDesC& aNumber, const TInt aMatchLengthFromRight) |
|
614 { |
|
615 return iContactsFile.FieldMatcher().MatchPhoneNumberL(aNumber, aMatchLengthFromRight); |
|
616 } |
|
617 |
|
618 |
|
619 /** |
|
620 Get a collection of contact IDs which have the given GUID. Since GUIDs are |
|
621 unique (i.e. no two contacts can have the same GUID) there will only ever be |
|
622 one contact ID in this collection. |
|
623 |
|
624 @param aGuid Contact GUID. |
|
625 |
|
626 @return Contact ID array containing the contact with the given GUID. |
|
627 */ |
|
628 CContactIdArray* CPlCollection::GuidL(const TDesC& aGuid) |
|
629 { |
|
630 // Create the database query string. |
|
631 TBuf<256> searchCond; |
|
632 _LIT(KFormat,"%S = '%S'"); |
|
633 searchCond.Format(KFormat, &KContactGuidString, &aGuid); |
|
634 |
|
635 RSqlStatement selectStatement; |
|
636 CleanupClosePushL(selectStatement); |
|
637 |
|
638 iSelectStatement->Reset(); |
|
639 iSelectStatement->SetParamL(KContactId, KSpace); |
|
640 iSelectStatement->SetConditionL(searchCond); |
|
641 |
|
642 User::LeaveIfError(selectStatement.Prepare(iContactsFile.NamedDatabase(), iSelectStatement->SqlStringL())); |
|
643 |
|
644 CContactIdArray* array = CContactIdArray::NewL(); |
|
645 CleanupStack::PushL(array); |
|
646 |
|
647 TInt idIndex = iSelectStatement->ParameterIndex(KContactId); |
|
648 TInt err; |
|
649 while((err = selectStatement.Next()) == KSqlAtRow) |
|
650 { |
|
651 array->AddL(selectStatement.ColumnInt(idIndex)); |
|
652 } |
|
653 |
|
654 if(err != KSqlAtEnd) |
|
655 { |
|
656 User::LeaveIfError(err); |
|
657 } |
|
658 |
|
659 CleanupStack::Pop(array); |
|
660 CleanupStack::PopAndDestroy(&selectStatement); |
|
661 |
|
662 return array; |
|
663 } |
|
664 |
|
665 |
|
666 /** |
|
667 Get a collection of contact IDs which have changed since the given time. |
|
668 |
|
669 @param aTime Changed since time. |
|
670 |
|
671 @return Contact ID array of those contacts which have changed since the given |
|
672 time. |
|
673 */ |
|
674 CContactIdArray* CPlCollection::ChangedSinceL(TTime aTime) |
|
675 { |
|
676 // Create the database query string. |
|
677 _LIT(KFormat,"%S >= %LD or %S >= %LD"); |
|
678 HBufC* searchCond = HBufC::NewLC(KFormat().Length()+ |
|
679 KContactCreationDate().Length()+KContactLastModified().Length()+ |
|
680 2 * 64); |
|
681 |
|
682 TPtr ptr = searchCond->Des(); |
|
683 ptr.Format(KFormat, &KContactCreationDate, aTime.Int64(), &KContactLastModified, aTime.Int64()); |
|
684 |
|
685 RSqlStatement selectStatement; |
|
686 CleanupClosePushL(selectStatement); |
|
687 |
|
688 iSelectStatement->Reset(); |
|
689 iSelectStatement->SetParamL(KContactId, KSpace); |
|
690 iSelectStatement->SetParamL(KContactTypeFlags, KSpace); |
|
691 iSelectStatement->SetConditionL(*searchCond); |
|
692 |
|
693 User::LeaveIfError(selectStatement.Prepare(iContactsFile.NamedDatabase(), iSelectStatement->SqlStringL())); |
|
694 |
|
695 CContactIdArray* array = CContactIdArray::NewL(); |
|
696 CleanupStack::PushL(array); |
|
697 |
|
698 const TInt idIndex = iSelectStatement->ParameterIndex(KContactId); |
|
699 const TInt typeFlagsIndex = iSelectStatement->ParameterIndex(KContactTypeFlags); |
|
700 TInt err; |
|
701 |
|
702 // Iterate through the view and include only those contacts of the desired |
|
703 // type (as determined by CheckType()). |
|
704 while((err = selectStatement.Next()) == KSqlAtRow) |
|
705 { |
|
706 TInt typeFlags = selectStatement.ColumnInt(typeFlagsIndex); |
|
707 TUid contactType = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags); |
|
708 if (iContactsFile.ContactProperties().CheckType(contactType)) |
|
709 { |
|
710 array->AddL(selectStatement.ColumnInt(idIndex)); |
|
711 } |
|
712 } |
|
713 |
|
714 if(err != KSqlAtEnd) |
|
715 { |
|
716 User::LeaveIfError(err); |
|
717 } |
|
718 |
|
719 CleanupStack::Pop(array); |
|
720 CleanupStack::PopAndDestroy(2,searchCond); // searchCond, selectStatement |
|
721 |
|
722 return array; |
|
723 } |
|
724 |
|
725 |
|
726 /** |
|
727 Get a collection of contact IDs which are 'unfiled'. |
|
728 |
|
729 @return Contact ID array of those contacts which are 'unfiled'. |
|
730 */ |
|
731 CContactIdArray* CPlCollection::UnfiledL() |
|
732 { |
|
733 RSqlStatement selectStmt; |
|
734 CleanupClosePushL(selectStmt); |
|
735 |
|
736 iSelectStatement->Reset(); |
|
737 iSelectStatement->SetParamL(KContactId, KSpace); |
|
738 iSelectStatement->SetParamL(KContactTypeFlags, KSpace); |
|
739 |
|
740 User::LeaveIfError(selectStmt.Prepare(iContactsFile.NamedDatabase(), iSelectStatement->SqlStringL())); |
|
741 |
|
742 CContactIdArray* array = CContactIdArray::NewL(); |
|
743 CleanupStack::PushL(array); |
|
744 |
|
745 TInt idIndex = iSelectStatement->ParameterIndex(KContactId); |
|
746 TInt typeFlagsIndex = iSelectStatement->ParameterIndex(KContactTypeFlags); |
|
747 |
|
748 // for WHERE contact_group_member_id = [contact id value] |
|
749 const TInt KWhereMemberClauseBufSize(KGroupContactGroupMemberId().Size() + KWhereStringEqualsStringFormatText().Size() + KGroupContactGroupMemberIdParam().Size() ); |
|
750 HBufC* whereMemberIdClause = HBufC::NewLC(KWhereMemberClauseBufSize); |
|
751 whereMemberIdClause->Des().AppendFormat(KWhereStringEqualsStringFormatText, &KGroupContactGroupMemberId, &KGroupContactGroupMemberIdParam ); |
|
752 |
|
753 // select group id |
|
754 // For a statement in the following format: |
|
755 // SELECT contact_group_id FROM groups |
|
756 // WHERE contact_group_member_id = [contact id value]; |
|
757 // |
|
758 TCntSqlStatementType statementType(ESelect, KSqlContactGroupTableName); |
|
759 CCntSqlStatement* selectGroupsStmnt = TSqlProvider::GetSqlStatementL(statementType); |
|
760 CleanupStack::PushL(selectGroupsStmnt); |
|
761 selectGroupsStmnt->SetParamL(KGroupContactGroupId(), KNullDesC() ); |
|
762 selectGroupsStmnt->SetConditionL(*whereMemberIdClause); |
|
763 const TInt KGroupContactGroupMemberIdParamIndex(KFirstIndex); // second parameter in the query |
|
764 |
|
765 TInt err; |
|
766 while((err = selectStmt.Next()) == KSqlAtRow) |
|
767 { |
|
768 TInt typeFlags = selectStmt.ColumnInt(typeFlagsIndex); |
|
769 TUid contactType = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags); |
|
770 TInt contactAttrib = (typeFlags & EContactAttributes_Mask) >> EContactAttributes_Shift; |
|
771 |
|
772 if (contactAttrib & CContactItem::EDeleted) |
|
773 { |
|
774 continue; |
|
775 } |
|
776 |
|
777 if (contactType == KUidContactCard || contactType == KUidContactOwnCard) |
|
778 { |
|
779 TInt contactId = selectStmt.ColumnInt(idIndex); |
|
780 |
|
781 RSqlStatement selectGroupSqlStmt; |
|
782 CleanupClosePushL(selectGroupSqlStmt); |
|
783 |
|
784 selectGroupSqlStmt.PrepareL(iContactsFile.NamedDatabase(), selectGroupsStmnt->SqlStringL() ); |
|
785 User::LeaveIfError(selectGroupSqlStmt.BindInt(KGroupContactGroupMemberIdParamIndex, contactId)); |
|
786 if((err = selectGroupSqlStmt.Next()) == KSqlAtEnd) |
|
787 { |
|
788 //add the contact id which is not in any group |
|
789 array->AddL(contactId); |
|
790 } |
|
791 |
|
792 User::LeaveIfError(err); |
|
793 CleanupStack::PopAndDestroy(&selectGroupSqlStmt); |
|
794 } |
|
795 } |
|
796 |
|
797 if(err != KSqlAtEnd) |
|
798 { |
|
799 User::LeaveIfError(err); |
|
800 } |
|
801 |
|
802 CleanupStack::PopAndDestroy(2, whereMemberIdClause); //whereMemberIdClause, selectGroupsStmnt # |
|
803 CleanupStack::Pop(array); |
|
804 CleanupStack::PopAndDestroy(&selectStmt); |
|
805 return array; |
|
806 } |
|
807 |
|
808 |
|
809 /** |
|
810 Get a collection of contact IDs which are marked as deleted. |
|
811 |
|
812 @return Contact ID array of those contacts which are marked as deleted. |
|
813 */ |
|
814 CContactIdArray* CPlCollection::DeletedL() |
|
815 { |
|
816 RSqlStatement selectStatement; |
|
817 CleanupClosePushL(selectStatement); |
|
818 |
|
819 iSelectStatement->Reset(); |
|
820 iSelectStatement->SetParamL(KContactId, KSpace); |
|
821 iSelectStatement->SetParamL(KContactTypeFlags, KSpace); |
|
822 |
|
823 User::LeaveIfError(selectStatement.Prepare(iContactsFile.NamedDatabase(), iSelectStatement->SqlStringL())); |
|
824 |
|
825 CContactIdArray* array = CContactIdArray::NewL(); |
|
826 CleanupStack::PushL(array); |
|
827 |
|
828 TInt idIndex = iSelectStatement->ParameterIndex(KContactId); |
|
829 TInt typeFlagsIndex = iSelectStatement->ParameterIndex(KContactTypeFlags); |
|
830 TInt err; |
|
831 while((err = selectStatement.Next()) == KSqlAtRow) |
|
832 { |
|
833 TInt typeFlags = selectStatement.ColumnInt(typeFlagsIndex); |
|
834 TInt contactAttrib = (typeFlags & EContactAttributes_Mask) >> EContactAttributes_Shift; |
|
835 |
|
836 if (contactAttrib & CContactItem::EDeleted) |
|
837 { |
|
838 array->AddL(selectStatement.ColumnInt(idIndex)); |
|
839 } |
|
840 } |
|
841 |
|
842 if(err != KSqlAtEnd) |
|
843 { |
|
844 User::LeaveIfError(err); |
|
845 } |
|
846 |
|
847 CleanupStack::Pop(array); |
|
848 CleanupStack::PopAndDestroy(&selectStatement); |
|
849 |
|
850 return array; |
|
851 } |
|
852 |
|
853 |
|
854 /** |
|
855 Perform a synchronous find for the given text and field definition. |
|
856 |
|
857 @param aText Text to find. |
|
858 @param aFieldDef Field definition to use. |
|
859 @param aSessionID |
|
860 |
|
861 @return Array of contact IDs resulting from the search. |
|
862 */ |
|
863 CContactIdArray* CPlCollection::FindL(const TDesC& aText, const CContactItemFieldDef* aFieldDef, TUint aSessionId) |
|
864 { |
|
865 CContactIdArray* idsFound = CContactIdArray::NewL(); |
|
866 CleanupStack::PushL(idsFound); |
|
867 |
|
868 // Create the "find text" from the given text. |
|
869 HBufC *findText = CreateFindTextL(aText); |
|
870 CleanupStack::PushL(findText); |
|
871 |
|
872 // Find out what tables need to included in the search as determined by the |
|
873 // given field definition. |
|
874 TInt findFlags = 0; |
|
875 TInt identityTableFieldsCount = 0; |
|
876 ConstructBitwiseFindFlags(findFlags,identityTableFieldsCount,aFieldDef); |
|
877 |
|
878 // Search through the first/last name (and their pronunciation) and company |
|
879 // names fields in the Identity table. |
|
880 if ( SearchIdentityFieldsRequired(findFlags) ) |
|
881 { |
|
882 _LIT(KWhereClause,"(%S LIKE '%S') OR (%S LIKE '%S') OR (%S LIKE '%S') OR (%S LIKE '%S') OR (%S LIKE '%S') OR (%S LIKE '%S')"); |
|
883 HBufC* searchCond = HBufC::NewLC(KWhereClause().Length() + |
|
884 KContactFirstName().Length() + findText->Length() + |
|
885 KContactLastName().Length() + findText->Length() + |
|
886 KContactCompanyName().Length() + findText->Length() + |
|
887 KContactFirstNamePrn().Length() + findText->Length() + |
|
888 KContactLastNamePrn().Length() + findText->Length() + |
|
889 KContactCompanyNamePrn().Length() + findText->Length()); |
|
890 searchCond->Des().Format(KWhereClause, &KContactFirstName, findText, |
|
891 &KContactLastName, findText, &KContactCompanyName, findText, |
|
892 &KContactFirstNamePrn, findText, &KContactLastNamePrn, findText, |
|
893 &KContactCompanyNamePrn, findText); |
|
894 |
|
895 RSqlStatement selectStatement; |
|
896 CleanupClosePushL(selectStatement); |
|
897 |
|
898 iSelectStatement->Reset(); |
|
899 iSelectStatement->SetParamL(KContactId, KSpace); |
|
900 iSelectStatement->SetParamL(KContactTypeFlags, KSpace); |
|
901 iSelectStatement->SetParamL(KContactFirstName, KSpace); |
|
902 iSelectStatement->SetParamL(KContactLastName, KSpace); |
|
903 iSelectStatement->SetParamL(KContactCompanyName, KSpace); |
|
904 iSelectStatement->SetParamL(KContactFirstNamePrn, KSpace); |
|
905 iSelectStatement->SetParamL(KContactLastNamePrn, KSpace); |
|
906 iSelectStatement->SetParamL(KContactCompanyNamePrn, KSpace); |
|
907 iSelectStatement->SetConditionL(*searchCond); |
|
908 |
|
909 User::LeaveIfError(selectStatement.Prepare(iContactsFile.NamedDatabase(), iSelectStatement->SqlStringL())); |
|
910 |
|
911 while(PerformFindIterationL(idsFound, aText, selectStatement, findFlags, aSessionId)) |
|
912 { |
|
913 // Keep performing find iteration until EFalse is returned. |
|
914 } |
|
915 |
|
916 CleanupStack::PopAndDestroy(2, searchCond); // searchCond, selectStatement |
|
917 } |
|
918 |
|
919 // Search through the email address fields |
|
920 if (findFlags & (EFindInAllFields | EFindInEmailField)) |
|
921 { |
|
922 TCntSqlStatementType statementType(ESelect, KSqlContactCommAddrTableName); |
|
923 CCntSqlStatement* cntSelectStatement = TSqlProvider::GetSqlStatementL(statementType); |
|
924 CleanupStack::PushL(cntSelectStatement); |
|
925 |
|
926 _LIT(KWhereClause, "(%S = %d) AND (%S LIKE '%S')"); |
|
927 HBufC* searchCond = HBufC::NewLC(KWhereClause().Length()+ |
|
928 KCommAddrType().Length() + |
|
929 KCommAddrValue().Length() + findText->Length()); |
|
930 searchCond->Des().Format(KWhereClause, |
|
931 &KCommAddrType, CPplCommAddrTable::EEmailAddress, |
|
932 &KCommAddrValue, findText); |
|
933 |
|
934 RSqlStatement selectStatement; |
|
935 CleanupClosePushL(selectStatement); |
|
936 |
|
937 cntSelectStatement->SetParamL(KContactId, KSpace); |
|
938 cntSelectStatement->SetConditionL(*searchCond); |
|
939 |
|
940 User::LeaveIfError(selectStatement.Prepare(iContactsFile.NamedDatabase(), cntSelectStatement->SqlStringL())); |
|
941 |
|
942 while(PerformIdFindIterationL(idsFound, selectStatement)) |
|
943 { |
|
944 // Keep performing find iteration until EFalse is returned. |
|
945 } |
|
946 |
|
947 CleanupStack::PopAndDestroy(3, cntSelectStatement); //selectStatement, searchCond, cntSelectStatement |
|
948 } |
|
949 |
|
950 // Search through the sip address fields |
|
951 if (findFlags & (EFindInAllFields | EFindInSIPField)) |
|
952 { |
|
953 TCntSqlStatementType statementType(ESelect, KSqlContactCommAddrTableName); |
|
954 CCntSqlStatement* cntSelectStatement = TSqlProvider::GetSqlStatementL(statementType); |
|
955 CleanupStack::PushL(cntSelectStatement); |
|
956 |
|
957 _LIT(KWhereClause, "(%S = %d) AND (%S LIKE '%S')"); |
|
958 HBufC* searchCond = HBufC::NewLC(KWhereClause().Length()+ |
|
959 KCommAddrType().Length() + |
|
960 KCommAddrValue().Length() + findText->Length()); |
|
961 searchCond->Des().Format(KWhereClause, |
|
962 &KCommAddrType, CPplCommAddrTable::ESipAddress, |
|
963 &KCommAddrValue, findText); |
|
964 |
|
965 RSqlStatement selectStatement; |
|
966 CleanupClosePushL(selectStatement); |
|
967 |
|
968 cntSelectStatement->SetParamL(KContactId, KSpace); |
|
969 cntSelectStatement->SetConditionL(*searchCond); |
|
970 |
|
971 User::LeaveIfError(selectStatement.Prepare(iContactsFile.NamedDatabase(), cntSelectStatement->SqlStringL())); |
|
972 |
|
973 while(PerformIdFindIterationL(idsFound, selectStatement)) |
|
974 { |
|
975 // Keep performing find iteration until EFalse is returned. |
|
976 } |
|
977 |
|
978 CleanupStack::PopAndDestroy(3, cntSelectStatement); //selectStatement, searchCond, cntSelectStatement |
|
979 } |
|
980 |
|
981 // Search through the searchable text for any other fields. |
|
982 if (findFlags & EFindInAllFields) |
|
983 { |
|
984 iSelectStatement->Reset(); |
|
985 iSelectStatement->SetParamL(KContactId, KSpace); |
|
986 iSelectStatement->SetParamL(KContactTypeFlags, KSpace); |
|
987 iSelectStatement->SetParamL(KContactTextFieldHeader, KSpace); |
|
988 iSelectStatement->SetParamL(KContactTextFields, KSpace); |
|
989 |
|
990 RSqlStatement selectStatement; |
|
991 CleanupClosePushL(selectStatement); |
|
992 |
|
993 User::LeaveIfError(selectStatement.Prepare(iContactsFile.NamedDatabase(), iSelectStatement->SqlStringL())); |
|
994 |
|
995 while(FindL(idsFound,*findText,aFieldDef, selectStatement, aSessionId)) |
|
996 { |
|
997 // Keep performing find iteration until EFalse is returned. |
|
998 } |
|
999 |
|
1000 CleanupStack::PopAndDestroy(&selectStatement); |
|
1001 } |
|
1002 |
|
1003 CleanupStack::PopAndDestroy(findText); |
|
1004 CleanupStack::Pop(idsFound); |
|
1005 |
|
1006 return(idsFound); |
|
1007 } |
|
1008 |
|
1009 |
|
1010 /** |
|
1011 Get a collection of contact IDs which match the given filter. |
|
1012 |
|
1013 @param aFilter Filter to match. |
|
1014 |
|
1015 @return Contact ID array of those contacts which match the given filter. |
|
1016 */ |
|
1017 CContactIdArray* CPlCollection::FilterDatabaseL(CCntFilter& aFilter) |
|
1018 { |
|
1019 _LIT(KWhereCondition,"%S >= %LD"); |
|
1020 |
|
1021 iSelectStatement->Reset(); |
|
1022 iSelectStatement->SetParamL(KContactId, KSpace); |
|
1023 iSelectStatement->SetParamL(KContactTypeFlags, KSpace); |
|
1024 |
|
1025 if (aFilter.IncludeModifiedContacts() || aFilter.IncludeDeletedContacts()) |
|
1026 { |
|
1027 // Create query to search for modified/deleted contacts. |
|
1028 HBufC* searchCond=HBufC::NewLC(KWhereCondition().Length() + |
|
1029 KContactLastModified().Length() + 64); |
|
1030 |
|
1031 TPtr ptr=searchCond->Des(); |
|
1032 ptr.Format(KWhereCondition, &KContactLastModified, aFilter.GetFilterDateTime().Int64()); |
|
1033 |
|
1034 iSelectStatement->SetConditionL(*searchCond); |
|
1035 |
|
1036 CleanupStack::PopAndDestroy(searchCond); |
|
1037 } |
|
1038 else if (aFilter.IncludeNewContacts()) |
|
1039 { |
|
1040 // Create query to search for inserted contacts. |
|
1041 HBufC* searchCond=HBufC::NewLC(KWhereCondition().Length() + |
|
1042 KContactCreationDate().Length() + 64); |
|
1043 |
|
1044 TPtr ptr=searchCond->Des(); |
|
1045 ptr.Format(KWhereCondition, &KContactCreationDate, aFilter.GetFilterDateTime().Int64()); |
|
1046 |
|
1047 iSelectStatement->SetConditionL(*searchCond); |
|
1048 |
|
1049 CleanupStack::PopAndDestroy(searchCond); |
|
1050 } |
|
1051 |
|
1052 RSqlStatement selectStatement; |
|
1053 CleanupClosePushL(selectStatement); |
|
1054 |
|
1055 const TInt idIndex = iSelectStatement->ParameterIndex(KContactId); |
|
1056 const TInt typeFlagsIndex = iSelectStatement->ParameterIndex(KContactTypeFlags); |
|
1057 |
|
1058 TBool filterIncludesAllContacts = !(aFilter.IncludeDeletedContacts() || |
|
1059 aFilter.IncludeNewContacts() || aFilter.IncludeModifiedContacts()); |
|
1060 |
|
1061 CContactIdArray* idArray = CContactIdArray::NewL(); |
|
1062 CleanupStack::PushL(idArray); |
|
1063 |
|
1064 User::LeaveIfError(selectStatement.Prepare(iContactsFile.NamedDatabase(), iSelectStatement->SqlStringL())); |
|
1065 |
|
1066 TInt err; |
|
1067 while((err = selectStatement.Next()) == KSqlAtRow) |
|
1068 { |
|
1069 TInt typeFlags = selectStatement.ColumnInt(typeFlagsIndex); |
|
1070 |
|
1071 TUid type = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags); |
|
1072 TUint32 attribs = (typeFlags & EContactAttributes_Mask) >> EContactAttributes_Shift; |
|
1073 |
|
1074 if (((aFilter.IncludeDeletedContacts() && (attribs & CContactItem::EDeleted)) |
|
1075 || (aFilter.IncludeNewContacts() |
|
1076 || aFilter.IncludeModifiedContacts()) && (aFilter.TestContactFilterType(type))) |
|
1077 || (filterIncludesAllContacts && aFilter.TestContactFilterType(type))) |
|
1078 { |
|
1079 TContactItemId id = selectStatement.ColumnInt(idIndex); |
|
1080 idArray->AddL(id); |
|
1081 } |
|
1082 } |
|
1083 |
|
1084 if(err != KSqlAtEnd) |
|
1085 { |
|
1086 User::LeaveIfError(err); |
|
1087 } |
|
1088 |
|
1089 CleanupStack::Pop(idArray); |
|
1090 CleanupStack::PopAndDestroy(&selectStatement); |
|
1091 |
|
1092 return idArray; |
|
1093 } |
|
1094 |
|
1095 |
|
1096 /** |
|
1097 Perform a find interation based on given sql statement for the given text. |
|
1098 |
|
1099 @param aIdsFound On return the contact IDs found. |
|
1100 @param aText Text to find. |
|
1101 @param aStatement sql statement |
|
1102 @param aFieldsToSearch Fields within the view to search. |
|
1103 @param aSessionId Session ID (only relevant for ICC contacts). |
|
1104 |
|
1105 @return ETrue if further iterations are required (i.e. view has not been fully |
|
1106 evaluated and searched), EFalse otherwise. |
|
1107 */ |
|
1108 TBool CPlCollection::PerformFindIterationL(CContactIdArray* aIdsFound,const TDesC& aText,RSqlStatement aStatement, TInt aFieldsToSearch, TUint aSessionId) |
|
1109 { |
|
1110 TContactItemId contactId; |
|
1111 |
|
1112 const TInt idIndex = aStatement.ColumnIndex(KContactId); |
|
1113 User::LeaveIfError(idIndex); |
|
1114 const TInt typeFlagsIndex = aStatement.ColumnIndex(KContactTypeFlags); |
|
1115 User::LeaveIfError(typeFlagsIndex); |
|
1116 TInt err; |
|
1117 |
|
1118 const TInt firstNameIndex = aStatement.ColumnIndex(KContactFirstName); |
|
1119 User::LeaveIfError(firstNameIndex); |
|
1120 const TInt lastNameIndex = aStatement.ColumnIndex(KContactLastName); |
|
1121 User::LeaveIfError(lastNameIndex); |
|
1122 const TInt companyNameIndex = aStatement.ColumnIndex(KContactCompanyName); |
|
1123 User::LeaveIfError(companyNameIndex); |
|
1124 const TInt firstNamePrnIndex = aStatement.ColumnIndex(KContactFirstNamePrn); |
|
1125 User::LeaveIfError(firstNamePrnIndex); |
|
1126 const TInt lastNamePrnIndex = aStatement.ColumnIndex(KContactLastNamePrn); |
|
1127 User::LeaveIfError(lastNamePrnIndex); |
|
1128 const TInt companyNamePrnIndex = aStatement.ColumnIndex(KContactCompanyNamePrn); |
|
1129 User::LeaveIfError(companyNamePrnIndex); |
|
1130 |
|
1131 while((err = aStatement.Next()) == KSqlAtRow) |
|
1132 { |
|
1133 // Do not include contact if it is not of the desired type. |
|
1134 TInt typeFlags = aStatement.ColumnInt(typeFlagsIndex); |
|
1135 TUid contactType = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags); |
|
1136 |
|
1137 if(iContactsFile.ContactProperties().CheckType(contactType) == EFalse) |
|
1138 { |
|
1139 continue; |
|
1140 } |
|
1141 |
|
1142 contactId = aStatement.ColumnInt(idIndex); |
|
1143 |
|
1144 // Check that the contact is not already present in the given contact |
|
1145 // IDs before searching for the given text. |
|
1146 if(aIdsFound->Find(contactId)==KErrNotFound) |
|
1147 { |
|
1148 TBool findTextInFields = ((aFieldsToSearch & EFindInAllFields) || (aFieldsToSearch & EFindFirstName)) ? (aStatement.ColumnTextL(firstNameIndex).FindC(aText.Ptr(), aText.Length(), KCollationLevel) != KErrNotFound ) : EFalse; |
|
1149 findTextInFields = findTextInFields || (((aFieldsToSearch & EFindInAllFields) || (aFieldsToSearch & EFindLastName)) ? (aStatement.ColumnTextL(lastNameIndex).FindC(aText.Ptr(), aText.Length(), KCollationLevel) != KErrNotFound ) : EFalse); |
|
1150 findTextInFields = findTextInFields || (((aFieldsToSearch & EFindInAllFields) || (aFieldsToSearch & EFindCompanyName)) ? (aStatement.ColumnTextL(companyNameIndex).FindC(aText.Ptr(), aText.Length(), KCollationLevel) != KErrNotFound ) : EFalse); |
|
1151 findTextInFields = findTextInFields || (((aFieldsToSearch & EFindInAllFields) || (aFieldsToSearch & EFindFirstNamePronunciation)) ? (aStatement.ColumnTextL(firstNamePrnIndex).FindC(aText.Ptr(), aText.Length(), KCollationLevel) != KErrNotFound ) :EFalse); |
|
1152 findTextInFields = findTextInFields || (((aFieldsToSearch & EFindInAllFields) || (aFieldsToSearch & EFindLastNamePronunciation)) ? (aStatement.ColumnTextL(lastNamePrnIndex).FindC(aText.Ptr(), aText.Length(), KCollationLevel) != KErrNotFound ) :EFalse); |
|
1153 findTextInFields = findTextInFields || (((aFieldsToSearch & EFindInAllFields) || (aFieldsToSearch & EFindCompanyNamePronunciation)) ? (aStatement.ColumnTextL(companyNamePrnIndex).FindC(aText.Ptr(), aText.Length(), KCollationLevel) != KErrNotFound ) : EFalse); |
|
1154 |
|
1155 if(findTextInFields) |
|
1156 { |
|
1157 if (contactType == KUidContactICCEntry) |
|
1158 { |
|
1159 TInt error(iContactsFile.ContactProperties().ContactSynchroniserL(aSessionId).ValidateContact(MContactSynchroniser::ESearch,contactId)); |
|
1160 User::LeaveIfError(error); |
|
1161 } |
|
1162 aIdsFound->AddL(contactId); |
|
1163 } |
|
1164 } |
|
1165 } |
|
1166 User::LeaveIfError(err); |
|
1167 |
|
1168 return (EFalse); |
|
1169 } |
|
1170 |
|
1171 /** |
|
1172 Perform a find interation based on the given sql statement for the given text. |
|
1173 |
|
1174 @param aIdsFound On return the contact IDs found. |
|
1175 @param aStatement sql statement |
|
1176 |
|
1177 @return ETrue if further iterations are required (i.e. view has not been fully |
|
1178 evaluated and searched), EFalse otherwise. |
|
1179 */ |
|
1180 TBool CPlCollection::PerformIdFindIterationL(CContactIdArray *aIdsFound, RSqlStatement aStatement) |
|
1181 { |
|
1182 const TInt idIndex = aStatement.ColumnIndex(KContactId); |
|
1183 User::LeaveIfError(idIndex); |
|
1184 TInt err; |
|
1185 while((err = aStatement.Next()) == KSqlAtRow) |
|
1186 { |
|
1187 TInt contactId = aStatement.ColumnInt(idIndex); |
|
1188 |
|
1189 // Check that the contact is not already present in the given contact |
|
1190 // IDs before adding it to the array of contact IDs. |
|
1191 if(aIdsFound->Find(contactId) == KErrNotFound) |
|
1192 { |
|
1193 aIdsFound->AddL(contactId); |
|
1194 } |
|
1195 } |
|
1196 User::LeaveIfError(err); |
|
1197 |
|
1198 return (EFalse); |
|
1199 } |
|
1200 |
|
1201 /** |
|
1202 Utility method used to build the search string |
|
1203 */ |
|
1204 void AppendSearchStringSegment(TDes16& aOrderFields,const TDesC& aColName, |
|
1205 const TPtrC aTxtPtr, TBool aAppendOr) |
|
1206 { |
|
1207 aOrderFields.Append(KLeftBracket); |
|
1208 aOrderFields.Append(aColName); |
|
1209 aOrderFields.Append(KLikeString); |
|
1210 aOrderFields.Append(aTxtPtr); |
|
1211 aOrderFields.Append(KLikeStringRight); |
|
1212 if(aAppendOr) |
|
1213 { |
|
1214 aOrderFields.Append(KOR); |
|
1215 } |
|
1216 } |
|
1217 |
|
1218 /** |
|
1219 Utility method used to build search string |
|
1220 */ |
|
1221 void ConstructSearchString(TInt aFieldDef,TInt aNoFields,TDes16& aOrderFields,TPtrC aTxtPtr) |
|
1222 { |
|
1223 const void* KColNamesFields[] = |
|
1224 { |
|
1225 &KContactFirstName, &KContactLastName, &KContactCompanyName, |
|
1226 &KContactFirstNamePrn, &KContactLastNamePrn, |
|
1227 &KContactLastNamePrn |
|
1228 }; |
|
1229 |
|
1230 for(TInt ii=0;ii<aNoFields;ii++) |
|
1231 { |
|
1232 for(TInt name = 0; name < sizeof(KNameFlags)/sizeof(TFindFieldFlags); ++name) |
|
1233 { |
|
1234 if(aFieldDef&KNameFlags[name]) |
|
1235 { |
|
1236 AppendSearchStringSegment(aOrderFields,*((TDesC*)KColNamesFields[name]), aTxtPtr, (ii+1)<aNoFields); |
|
1237 aFieldDef &= ~KNameFlags[name]; |
|
1238 break; |
|
1239 } |
|
1240 } |
|
1241 } |
|
1242 } |
|
1243 |
|
1244 |
|
1245 /** |
|
1246 This method is required for asynchronous finds which have an initialisation |
|
1247 method followed by one or more calls to the FindAsyncL() method. The class |
|
1248 needs to be reset to a known state when a find is completed. |
|
1249 */ |
|
1250 void CPlCollection::Reset() |
|
1251 { |
|
1252 if ( !iRSqlstatementsWorking ) |
|
1253 { |
|
1254 //If RSqlstatements was reseted, don't reset it again. |
|
1255 return; |
|
1256 } |
|
1257 // Could introduce methods specific to the find operation such that this |
|
1258 // method is called only if an asynchronous find has taken place. |
|
1259 delete iFieldDef; |
|
1260 iFieldDef = NULL; |
|
1261 delete iTextDef; |
|
1262 iTextDef = NULL; |
|
1263 delete iText; |
|
1264 iText = NULL; |
|
1265 delete iOriginalText; |
|
1266 iOriginalText = NULL; |
|
1267 delete iFindWords; |
|
1268 iFindWords = NULL; |
|
1269 delete iFindWords2; |
|
1270 iFindWords2 = NULL; |
|
1271 iNoIdentitySearchColumns = 0; |
|
1272 iFindFlags = 0; |
|
1273 iFindState = 0; |
|
1274 |
|
1275 selectBlobStatement.Close(); |
|
1276 selectIdentityStatement.Close(); |
|
1277 selectEmailStatement.Close(); |
|
1278 selectSIPStatement.Close(); |
|
1279 selectIdFromIdentityStatement.Close(); |
|
1280 iRSqlstatementsWorking = EFalse; |
|
1281 } |
|
1282 |
|
1283 |
|
1284 /** |
|
1285 Initialise the Persistence Layer collection class ready for iterative calls to |
|
1286 the FindAsyncL() method. This form of initialisation is for an asynchronous |
|
1287 find which uses text and a field definition. |
|
1288 |
|
1289 @param aText Find text. |
|
1290 @param aFieldDef Field definition to use in find. |
|
1291 |
|
1292 @leave KErrNoMemory Out of memory. |
|
1293 */ |
|
1294 void CPlCollection::FindAsyncInitL(const TDesC& aText,CContactItemFieldDef* aFieldDef) |
|
1295 { |
|
1296 _LIT(KWhereEmailSIPClause, "(%S = %d) AND (%S LIKE '%S')"); |
|
1297 // Persistence Layer CPlCollection is not deleted but Reset()'s the member |
|
1298 // variables for iterative FindAsyncL() calls. |
|
1299 Reset(); |
|
1300 iRSqlstatementsWorking = ETrue; |
|
1301 iText = CreateFindTextL(aText); |
|
1302 iFieldDef = aFieldDef; |
|
1303 iOriginalText = aText.AllocL(); |
|
1304 ConstructBitwiseFindFlags(iFindFlags,iNoIdentitySearchColumns,iFieldDef); |
|
1305 // Construct RSqlStatements used for search |
|
1306 |
|
1307 HBufC *findText = CreateFindTextL(*iOriginalText); |
|
1308 CleanupStack::PushL(findText); |
|
1309 |
|
1310 // first construct select statement for searching in identity fields |
|
1311 if ( SearchIdentityFieldsRequired(iFindFlags) ) |
|
1312 { |
|
1313 _LIT(KWhereClause,"(%S LIKE '%S') OR (%S LIKE '%S') OR (%S LIKE '%S') OR (%S LIKE '%S') OR (%S LIKE '%S') OR (%S LIKE '%S')"); |
|
1314 HBufC* searchCond=HBufC::NewLC(KWhereClause().Length() + |
|
1315 KContactFirstName().Length() + findText->Length() + |
|
1316 KContactLastName().Length() + findText->Length() + |
|
1317 KContactCompanyName().Length() + findText->Length() + |
|
1318 KContactFirstNamePrn().Length() + findText->Length() + |
|
1319 KContactLastNamePrn().Length() + findText->Length() + |
|
1320 KContactCompanyNamePrn().Length() + findText->Length()); |
|
1321 searchCond->Des().Format(KWhereClause, &KContactFirstName, findText, |
|
1322 &KContactLastName, findText, &KContactCompanyName, findText, |
|
1323 &KContactFirstNamePrn, findText, &KContactLastNamePrn, findText, |
|
1324 &KContactCompanyNamePrn, findText); |
|
1325 |
|
1326 iSelectStatement->Reset(); |
|
1327 iSelectStatement->SetParamL(KContactId, KSpace); |
|
1328 iSelectStatement->SetParamL(KContactTypeFlags, KSpace); |
|
1329 iSelectStatement->SetParamL(KContactFirstName, KSpace); |
|
1330 iSelectStatement->SetParamL(KContactLastName, KSpace); |
|
1331 iSelectStatement->SetParamL(KContactCompanyName, KSpace); |
|
1332 iSelectStatement->SetParamL(KContactFirstNamePrn, KSpace); |
|
1333 iSelectStatement->SetParamL(KContactLastNamePrn, KSpace); |
|
1334 iSelectStatement->SetParamL(KContactCompanyNamePrn, KSpace); |
|
1335 iSelectStatement->SetConditionL(*searchCond); |
|
1336 |
|
1337 User::LeaveIfError(selectIdentityStatement.Prepare(iContactsFile.NamedDatabase(), iSelectStatement->SqlStringL())); |
|
1338 CleanupStack::PopAndDestroy(searchCond); |
|
1339 } |
|
1340 //end construction for statement for searching in identity fields |
|
1341 |
|
1342 //construct statement for search email |
|
1343 if (iFindFlags & (EFindInAllFields | EFindInEmailField)) |
|
1344 { |
|
1345 TCntSqlStatementType statementType(ESelect, KSqlContactCommAddrTableName); |
|
1346 CCntSqlStatement* cntSelectStatement = TSqlProvider::GetSqlStatementL(statementType); |
|
1347 CleanupStack::PushL(cntSelectStatement); |
|
1348 |
|
1349 HBufC* searchCond = HBufC::NewLC(KWhereEmailSIPClause().Length()+ |
|
1350 KCommAddrType().Length() + |
|
1351 KCommAddrValue().Length() + findText->Length()); |
|
1352 searchCond->Des().Format(KWhereEmailSIPClause, |
|
1353 &KCommAddrType, CPplCommAddrTable::EEmailAddress, |
|
1354 &KCommAddrValue, findText); |
|
1355 |
|
1356 cntSelectStatement->SetParamL(KContactId, KSpace); |
|
1357 cntSelectStatement->SetConditionL(*searchCond); |
|
1358 |
|
1359 User::LeaveIfError(selectEmailStatement.Prepare(iContactsFile.NamedDatabase(), cntSelectStatement->SqlStringL())); |
|
1360 CleanupStack::PopAndDestroy(2, cntSelectStatement); // cntSelectStatement, searchCond |
|
1361 } |
|
1362 //end construction for statement for search email |
|
1363 |
|
1364 //construct statement for search sip values |
|
1365 if (iFindFlags & (EFindInAllFields | EFindInSIPField)) |
|
1366 { |
|
1367 TCntSqlStatementType statementType(ESelect, KSqlContactCommAddrTableName); |
|
1368 CCntSqlStatement* cntSelectStatement = TSqlProvider::GetSqlStatementL(statementType); |
|
1369 CleanupStack::PushL(cntSelectStatement); |
|
1370 |
|
1371 HBufC* searchCond = HBufC::NewLC(KWhereEmailSIPClause().Length()+ |
|
1372 KCommAddrType().Length() + |
|
1373 KCommAddrValue().Length() + findText->Length()); |
|
1374 searchCond->Des().Format(KWhereEmailSIPClause, |
|
1375 &KCommAddrType, CPplCommAddrTable::ESipAddress, |
|
1376 &KCommAddrValue, findText); |
|
1377 |
|
1378 cntSelectStatement->SetParamL(KContactId, KSpace); |
|
1379 cntSelectStatement->SetConditionL(*searchCond); |
|
1380 |
|
1381 User::LeaveIfError(selectSIPStatement.Prepare(iContactsFile.NamedDatabase(), cntSelectStatement->SqlStringL())); |
|
1382 CleanupStack::PopAndDestroy(2, cntSelectStatement); // cntSelectStatement, searchCond |
|
1383 } |
|
1384 //end construction for statement for search sip values |
|
1385 |
|
1386 //construct statement for search in blob |
|
1387 if (iFindFlags & EFindInAllFields) |
|
1388 { |
|
1389 iSelectStatement->Reset(); |
|
1390 iSelectStatement->SetParamL(KContactId, KSpace); |
|
1391 iSelectStatement->SetParamL(KContactTypeFlags, KSpace); |
|
1392 iSelectStatement->SetParamL(KContactTextFieldHeader, KSpace); |
|
1393 iSelectStatement->SetParamL(KContactTextFields, KSpace); |
|
1394 |
|
1395 User::LeaveIfError(selectBlobStatement.Prepare(iContactsFile.NamedDatabase(), iSelectStatement->SqlStringL())); |
|
1396 } |
|
1397 //end construction for statement for search in blob |
|
1398 |
|
1399 CleanupStack::PopAndDestroy(findText); |
|
1400 } |
|
1401 |
|
1402 |
|
1403 /** |
|
1404 Add the required fields and search text for SQL query. Used for asynchronous |
|
1405 find which uses a text definition. |
|
1406 |
|
1407 @see CPlCollection::FindAsyncTextDefInitL() |
|
1408 |
|
1409 @param aOrderFields On return contains the required fields and search text for |
|
1410 SQL query. |
|
1411 */ |
|
1412 void CPlCollection::doAppendFieldsToSearchString(HBufC* aOrderFields) const |
|
1413 { |
|
1414 TInt noOfFindWords = iFindWords2->Count(); |
|
1415 TPtr16 orderFieldPtr = aOrderFields->Des(); |
|
1416 for(TInt searchWord = 0;searchWord < noOfFindWords; ++searchWord) |
|
1417 { |
|
1418 ConstructSearchString(iFindFlags,iNoIdentitySearchColumns,orderFieldPtr,(*iFindWords2)[searchWord]); |
|
1419 if ((searchWord+1) < noOfFindWords) |
|
1420 { |
|
1421 orderFieldPtr.Append(KOR); |
|
1422 } |
|
1423 } |
|
1424 } |
|
1425 |
|
1426 |
|
1427 /** |
|
1428 Initialise the Persistence Layer collection class ready for iterative calls to |
|
1429 the FindAsyncL() method. This form of initialisation is for an asynchronous |
|
1430 find which uses a text definition and an array of "find words". |
|
1431 |
|
1432 @param aWords "Find words" array. |
|
1433 @param aTextDef Text definition to use in find. |
|
1434 */ |
|
1435 void CPlCollection::FindAsyncTextDefInitL(const CDesCArray& aWords,CContactTextDef* aTextDef) |
|
1436 { |
|
1437 // Persistence Layer CPlCollection is not deleted but Reset()'s the member |
|
1438 // variables for iterative FindAsyncL() calls. |
|
1439 Reset(); |
|
1440 iRSqlstatementsWorking = ETrue; |
|
1441 iFindWords = new(ELeave) CDesCArrayFlat(5); |
|
1442 iFindWords2 = new(ELeave) CDesCArrayFlat(5); |
|
1443 for(TInt loop = 0;loop < aWords.MdcaCount();++loop) |
|
1444 { |
|
1445 // Construct iFindWords2 which contains all the strings in the search |
|
1446 // surrounded by a %. |
|
1447 TPtrC findWord(aWords.MdcaPoint(loop)); |
|
1448 TKeyCmpTextLength key; |
|
1449 HBufC* bufPtr = findWord.AllocLC(); |
|
1450 iFindWords->CArrayFixBase::InsertIsqAllowDuplicatesL(&bufPtr,key); |
|
1451 CleanupStack::Pop(); // bufPtr |
|
1452 HBufC *findText = CreateFindTextL(findWord); |
|
1453 CleanupStack::PushL(findText); |
|
1454 iFindWords2->AppendL(*findText); |
|
1455 CleanupStack::PopAndDestroy(); // findText |
|
1456 } |
|
1457 |
|
1458 iTextDef = aTextDef; |
|
1459 ConstructBitwiseFlagsFromTextDef(iFindFlags,iNoIdentitySearchColumns,iTextDef); |
|
1460 |
|
1461 iSelectStatement->Reset(); |
|
1462 iSelectStatement->SetParamL(KContactId, KSpace); |
|
1463 iSelectStatement->SetParamL(KContactTypeFlags, KSpace); |
|
1464 iSelectStatement->SetParamL(KContactFirstName, KSpace); |
|
1465 iSelectStatement->SetParamL(KContactLastName, KSpace); |
|
1466 iSelectStatement->SetParamL(KContactCompanyName, KSpace); |
|
1467 iSelectStatement->SetParamL(KContactFirstNamePrn, KSpace); |
|
1468 iSelectStatement->SetParamL(KContactLastNamePrn, KSpace); |
|
1469 iSelectStatement->SetParamL(KContactCompanyNamePrn, KSpace); |
|
1470 |
|
1471 if(UsesIdentityFieldsOnly(iFindFlags)) |
|
1472 { |
|
1473 TInt querySize = ApproximateSizeOfSearchString(); |
|
1474 HBufC* searchCond = HBufC::NewLC(querySize); |
|
1475 doAppendFieldsToSearchString(searchCond); |
|
1476 iSelectStatement->SetConditionL(*searchCond); |
|
1477 CleanupStack::PopAndDestroy(searchCond); |
|
1478 } |
|
1479 |
|
1480 User::LeaveIfError(selectIdFromIdentityStatement.Prepare(iContactsFile.NamedDatabase(), iSelectStatement->SqlStringL())); |
|
1481 } |
|
1482 |
|
1483 |
|
1484 /** |
|
1485 This method does not do any searching. It simply extracts the contact IDs from |
|
1486 the view and (ultimately) returns them to the CIdleFinder object on the client |
|
1487 side. |
|
1488 |
|
1489 The client can then call CIdleFinder::CheckFindL() to perform the actual search. |
|
1490 Searching cannot be performed server-side because of the need to call a client |
|
1491 supplied callback method (the "find words parser" callback). |
|
1492 |
|
1493 @param aIdArray Contact IDs extracted from the view. |
|
1494 @param aSessionId Session ID (only relevant for ICC contacts). |
|
1495 |
|
1496 @return ETrue if further iterations are required (i.e. view has not been fully |
|
1497 evaluated), EFalse otherwise. |
|
1498 */ |
|
1499 TBool CPlCollection::GetContactIdsForTextDefFindL(CContactIdArray* aIdArray, TUint aSessionId) |
|
1500 { |
|
1501 TInt iterCount = 0; |
|
1502 TInt err; |
|
1503 |
|
1504 const TInt idIndex = selectIdFromIdentityStatement.ColumnIndex(KContactId); |
|
1505 User::LeaveIfError(idIndex); |
|
1506 const TInt typeFlagsIndex = selectIdFromIdentityStatement.ColumnIndex(KContactTypeFlags); |
|
1507 User::LeaveIfError(typeFlagsIndex); |
|
1508 |
|
1509 while(iterCount<KFindIterations) |
|
1510 { |
|
1511 err = selectIdFromIdentityStatement.Next(); |
|
1512 if(err != KSqlAtRow) |
|
1513 { |
|
1514 User::LeaveIfError(err); |
|
1515 break; |
|
1516 } |
|
1517 |
|
1518 TInt typeFlags = selectIdFromIdentityStatement.ColumnInt(typeFlagsIndex); |
|
1519 TUid contactType = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags); |
|
1520 TContactItemId contactId = selectIdFromIdentityStatement.ColumnInt(idIndex); |
|
1521 |
|
1522 if (contactType == KUidContactICCEntry) |
|
1523 { |
|
1524 User::LeaveIfError(iContactsFile.ContactProperties().ContactSynchroniserL(aSessionId).ValidateContact(MContactSynchroniser::ESearch,contactId)); |
|
1525 User::LeaveIfError(iContactsFile.ContactProperties().ContactSynchroniserL(aSessionId).ValidateContact(MContactSynchroniser::ERead,contactId)); |
|
1526 } |
|
1527 // Check that the contact is not already present in the given |
|
1528 // contact IDs before adding to array. |
|
1529 if(aIdArray->Find(contactId) == KErrNotFound) |
|
1530 { |
|
1531 aIdArray->AddL(contactId); |
|
1532 } |
|
1533 } |
|
1534 |
|
1535 return(iterCount == KFindIterations); |
|
1536 } |
|
1537 |
|
1538 |
|
1539 /** |
|
1540 Perform an asynchronous find iteration. |
|
1541 |
|
1542 @param aMoreToGo On return ETrue if further iterations are required to complete |
|
1543 the asynchronous find, EFalse otherwise. |
|
1544 @param aSessionId Session ID (only relevant for ICC contacts). |
|
1545 |
|
1546 @return Array of contact ID found in this find iteration. |
|
1547 */ |
|
1548 CContactIdArray* CPlCollection::FindAsyncL(TBool& aMoreToGo, TUint aSessionId) |
|
1549 { |
|
1550 CContactIdArray* idArray = CContactIdArray::NewLC(); |
|
1551 TBool moreToGo = EFalse; |
|
1552 |
|
1553 if (iFindWords) // Text definition and "find words". |
|
1554 { |
|
1555 TRAPD(err, moreToGo=GetContactIdsForTextDefFindL(idArray, aSessionId)); |
|
1556 |
|
1557 if (err != KErrNone) |
|
1558 { |
|
1559 moreToGo = EFalse; |
|
1560 Reset(); |
|
1561 User::Leave(err); |
|
1562 } |
|
1563 |
|
1564 if(moreToGo == EFalse) |
|
1565 { |
|
1566 iFindState |= EFindInTextDefFinished; |
|
1567 } |
|
1568 } |
|
1569 else // Search for a single string. |
|
1570 { |
|
1571 if(!(iFindState & EFindInBlobFinished) && (iFindFlags & EFindInAllFields)) |
|
1572 { |
|
1573 // Search in searchable text (contents of BLOB). |
|
1574 if(!FindL(idArray, *iText, iFieldDef, selectBlobStatement, aSessionId)) |
|
1575 { |
|
1576 iFindState |= EFindInBlobFinished; |
|
1577 } |
|
1578 else |
|
1579 { |
|
1580 moreToGo = ETrue; |
|
1581 } |
|
1582 } |
|
1583 |
|
1584 if(!(iFindState & EFindInIdentityFinished)) |
|
1585 { |
|
1586 if(SearchIdentityFieldsRequired(iFindFlags)) |
|
1587 { |
|
1588 // Search in identity fields. |
|
1589 if(!PerformFindIterationL(idArray, *iOriginalText, selectIdentityStatement, iFindFlags, aSessionId)) |
|
1590 { |
|
1591 iFindState |= EFindInIdentityFinished; |
|
1592 } |
|
1593 else |
|
1594 { |
|
1595 moreToGo = ETrue; |
|
1596 } |
|
1597 } |
|
1598 } |
|
1599 |
|
1600 if(!(iFindState & EFindInEmailFinished)) |
|
1601 { |
|
1602 if(iFindFlags & (EFindInAllFields | EFindInEmailField)) |
|
1603 { |
|
1604 // Search in email fields. |
|
1605 if(!PerformIdFindIterationL(idArray, selectEmailStatement)) |
|
1606 { |
|
1607 iFindState |= EFindInEmailFinished; |
|
1608 } |
|
1609 else |
|
1610 { |
|
1611 moreToGo = ETrue; |
|
1612 } |
|
1613 } |
|
1614 } |
|
1615 |
|
1616 if(!(iFindState & EFindInSIPFinished)) |
|
1617 { |
|
1618 if(iFindFlags & (EFindInAllFields | EFindInSIPField)) |
|
1619 { |
|
1620 // Search in email fields. |
|
1621 if(!PerformIdFindIterationL(idArray, selectSIPStatement)) |
|
1622 { |
|
1623 iFindState |= EFindInSIPFinished; |
|
1624 } |
|
1625 else |
|
1626 { |
|
1627 moreToGo = ETrue; |
|
1628 } |
|
1629 } |
|
1630 } |
|
1631 } |
|
1632 |
|
1633 |
|
1634 if(!moreToGo) |
|
1635 { |
|
1636 Reset(); |
|
1637 } |
|
1638 |
|
1639 /* |
|
1640 // Check if we have finished searching. |
|
1641 if ((iFindState&(EFindInBlobFinished|EFindInIdentityFinished|EFindInEmailFinished)) == (EFindInBlobFinished|EFindInIdentityFinished|EFindInEmailFinished) |
|
1642 || iFindState&EFindInTextDefFinished) |
|
1643 { |
|
1644 moreToGo = EFalse; |
|
1645 Reset(); |
|
1646 } |
|
1647 */ |
|
1648 aMoreToGo = moreToGo; |
|
1649 |
|
1650 // Pop this off the cleanup stack, as we are passing on ownership to the calling method |
|
1651 CleanupStack::Pop(idArray); |
|
1652 |
|
1653 return idArray; |
|
1654 } |
|
1655 |
|
1656 |
|
1657 /** |
|
1658 Perform a synchronous find for the given text and field definition. |
|
1659 |
|
1660 @param aIdsFound Contacts IDs found. |
|
1661 @param aText Text to search for. |
|
1662 @param aFieldDef Field definition to use. |
|
1663 @param aSessionId Session ID (only relevant for ICC contacts). |
|
1664 |
|
1665 @return ETrue if all iterations have been completed, EFalse otherwise. |
|
1666 */ |
|
1667 TBool CPlCollection::FindL(CContactIdArray *aIdsFound, const TDesC& aText,const CContactItemFieldDef *aFieldDef, RSqlStatement aStatement, TUint aSessionId) |
|
1668 { |
|
1669 const CContactTemplate& systemTemplate = iContactsFile.ContactProperties().SystemTemplateManager().TemplateL(); |
|
1670 |
|
1671 CContactItemField* field = CContactItemField::NewLC(); // construct just once |
|
1672 |
|
1673 TInt endOfQueryString = aText.Length()-2; |
|
1674 TPtrC originalFindText = aText.Mid(1,endOfQueryString); |
|
1675 |
|
1676 TInt iterCount = 0; |
|
1677 TInt err; |
|
1678 |
|
1679 const TInt idIndex = aStatement.ColumnIndex(KContactId); |
|
1680 User::LeaveIfError(idIndex); |
|
1681 const TInt typeFlagsIndex = aStatement.ColumnIndex(KContactTypeFlags); |
|
1682 User::LeaveIfError(typeFlagsIndex); |
|
1683 const TInt textHeaderIndex = aStatement.ColumnIndex(KContactTextFieldHeader); |
|
1684 User::LeaveIfError(textHeaderIndex); |
|
1685 const TInt textFieldsIndex = aStatement.ColumnIndex(KContactTextFields); |
|
1686 User::LeaveIfError(textFieldsIndex); |
|
1687 |
|
1688 while(iterCount<KFindIterations) |
|
1689 { |
|
1690 err = aStatement.Next(); |
|
1691 if(err != KSqlAtRow) |
|
1692 { |
|
1693 User::LeaveIfError(err); |
|
1694 break; |
|
1695 } |
|
1696 |
|
1697 TInt typeFlags = aStatement.ColumnInt(typeFlagsIndex); |
|
1698 TUid contactType = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags); |
|
1699 |
|
1700 if (iContactsFile.ContactProperties().CheckType(contactType) ) |
|
1701 { |
|
1702 TPtrC8 textHeader; |
|
1703 aStatement.ColumnBinary(textHeaderIndex, textHeader); |
|
1704 RDesReadStream textHeaderStream(textHeader); |
|
1705 CleanupClosePushL(textHeaderStream); |
|
1706 |
|
1707 CEmbeddedStore* store = CEmbeddedStore::FromLC(textHeaderStream); |
|
1708 |
|
1709 TPtrC textFieldPtrC = aStatement.ColumnTextL(textFieldsIndex); |
|
1710 HBufC *textBuf = HBufC::NewLC(textFieldPtrC.Size()); |
|
1711 textBuf->Des().Copy(textFieldPtrC); |
|
1712 |
|
1713 RStoreReadStream rootStream; |
|
1714 rootStream.OpenLC(*store ,store->Root()); |
|
1715 |
|
1716 TCardinality count; |
|
1717 rootStream >> count; |
|
1718 |
|
1719 for (TInt i = 0;i < count; ++i) |
|
1720 { |
|
1721 field->Reset(); |
|
1722 if (field->RestoreIfMatchL(rootStream,aFieldDef,&systemTemplate.CardFields(),textBuf,i)) |
|
1723 { |
|
1724 if (field->StorageType() == KStorageTypeText && |
|
1725 field->TextStorage()->Text().FindC(originalFindText.Ptr(), |
|
1726 originalFindText.Length(), KCollationLevel) != KErrNotFound) |
|
1727 { |
|
1728 TContactItemId id = aStatement.ColumnInt(idIndex); |
|
1729 if(aIdsFound->Find(id) == KErrNotFound) |
|
1730 { |
|
1731 if (contactType == KUidContactICCEntry) |
|
1732 { |
|
1733 TInt error(iContactsFile.ContactProperties().ContactSynchroniserL(aSessionId).ValidateContact(MContactSynchroniser::ESearch,id)); |
|
1734 User::LeaveIfError(error); |
|
1735 } |
|
1736 aIdsFound->AddL(id); |
|
1737 } |
|
1738 break; |
|
1739 } |
|
1740 } |
|
1741 } |
|
1742 CleanupStack::PopAndDestroy(4, &textHeaderStream); // rootStream, textBuf, textHeader, textHeaderStream |
|
1743 } |
|
1744 ++iterCount; |
|
1745 } |
|
1746 |
|
1747 CleanupStack::PopAndDestroy(field); |
|
1748 |
|
1749 return(iterCount == KFindIterations); |
|
1750 } |
|
1751 |
|
1752 /** |
|
1753 Return an over-estimated string size for the amount of syntax required per field |
|
1754 per search string for the Identity table. |
|
1755 |
|
1756 @return Maximum string size required for Identity table search syntax. |
|
1757 */ |
|
1758 TInt CPlCollection::MaximumSizeOfIdentitySearchSyntax() |
|
1759 { |
|
1760 TInt sqlLitSize; |
|
1761 |
|
1762 sqlLitSize = KLeftBracket().Length() + KLikeString().Length() + |
|
1763 KLikeStringRight().Length() + KOR().Length(); |
|
1764 |
|
1765 sqlLitSize *= iNoIdentitySearchColumns; |
|
1766 |
|
1767 sqlLitSize += KContactFirstName().Length() + KContactLastName().Length() + |
|
1768 KContactCompanyName().Length(); |
|
1769 |
|
1770 sqlLitSize += KContactFirstNamePrn().Length() + |
|
1771 KContactLastNamePrn().Length() + |
|
1772 KContactCompanyNamePrn().Length(); |
|
1773 |
|
1774 return(sqlLitSize); |
|
1775 } |
|
1776 |
|
1777 /** |
|
1778 Determine the approximate size of the string required to construct the SQL query |
|
1779 on the Identity table when using the "find words". |
|
1780 |
|
1781 @return Approximate size of search string. |
|
1782 */ |
|
1783 TInt CPlCollection::ApproximateSizeOfSearchString() |
|
1784 { |
|
1785 TInt sqlLitSize = MaximumSizeOfIdentitySearchSyntax(); |
|
1786 |
|
1787 TInt noOfFindWords=iFindWords2->Count(); |
|
1788 TInt size=0; |
|
1789 |
|
1790 for(TInt searchWord=0;searchWord < noOfFindWords; ++searchWord) |
|
1791 { |
|
1792 size += (*iFindWords2)[searchWord].Length(); |
|
1793 } |
|
1794 |
|
1795 TInt totalSize = noOfFindWords*sqlLitSize + iNoIdentitySearchColumns*size + 256; |
|
1796 |
|
1797 return totalSize; |
|
1798 } |
|
1799 |
|
1800 /** |
|
1801 Utility method used to filter hint fields |
|
1802 */ |
|
1803 TBool CPlCollection::HintFieldMatchesFilter(TInt aHintField, TInt aFilter) |
|
1804 { |
|
1805 TBool match=EFalse; |
|
1806 |
|
1807 if (aFilter==CContactDatabase::EUnfiltered) |
|
1808 { |
|
1809 return ETrue; |
|
1810 } |
|
1811 |
|
1812 if (aFilter & ~aHintField & (CContactDatabase::EWork | CContactDatabase::EHome)) |
|
1813 { |
|
1814 return EFalse; |
|
1815 } |
|
1816 |
|
1817 match = aFilter & aHintField |
|
1818 & ( |
|
1819 CContactDatabase::ELandLine |
|
1820 | CContactDatabase::ESmsable |
|
1821 | CContactDatabase::EMailable |
|
1822 | CContactDatabase::EFaxable |
|
1823 | CContactDatabase::EPhonable |
|
1824 | CContactDatabase::ERingTone |
|
1825 | CContactDatabase::EVoiceDial |
|
1826 | CContactDatabase::EIMAddress |
|
1827 | CContactDatabase::EWirelessVillage |
|
1828 | CContactDatabase::ECustomFilter1 |
|
1829 | CContactDatabase::ECustomFilter2 |
|
1830 | CContactDatabase::ECustomFilter3 |
|
1831 | CContactDatabase::ECustomFilter4 |
|
1832 ); |
|
1833 |
|
1834 return match; |
|
1835 } |