|
1 // Copyright (c) 2003-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 #include "LOGFILTQ.H" |
|
17 #include <logcli.h> |
|
18 #include <logcntdef.h> |
|
19 #include "logservpanic.h" |
|
20 #include "LogServDatabaseTransactionInterface.h" |
|
21 #include <logfilterandeventconstants.hrh> |
|
22 #include "LogServCacheStrings.h" |
|
23 #include "LogServCacheTypes.h" |
|
24 #include "LogServSqlStrings.h" |
|
25 |
|
26 #ifdef _DEBUG |
|
27 # define __LOGFILTQ_INVARIANT() Invariant() |
|
28 #else |
|
29 # define __LOGFILTQ_INVARIANT() void(0) |
|
30 #endif |
|
31 |
|
32 /** |
|
33 KFilterFields array contains all fields that can participate in a filter. |
|
34 The term "field" refers a constant, which value is power of two. |
|
35 Every "field" uniquely identifies one of the event properties. |
|
36 The field values are used in the implementation of the TLogFilterExprBuilder class for initializing the |
|
37 iField data member, used to identify the currently processed event property value. |
|
38 @internalComponent |
|
39 */ |
|
40 const TUint16 KFilterFields[] = |
|
41 { |
|
42 ELogContactField, |
|
43 ELogDirectionField, |
|
44 ELogDurationTypeField, |
|
45 ELogEventTypeField, |
|
46 ELogNumberField, |
|
47 ELogRemotePartyField, |
|
48 ELogStatusField, |
|
49 ELogStartTimeField, |
|
50 ELogEndTimeField, |
|
51 #ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM |
|
52 ELogSimIdField, //The new ELogSimIdField must be before the flags: see |
|
53 //DoNextProcessFieldByFieldFilterByFilterL() implementation and the assert. |
|
54 #endif |
|
55 ELogFlagsField |
|
56 }; |
|
57 |
|
58 /** |
|
59 The size of the KFilterFields array. |
|
60 @internalComponent |
|
61 */ |
|
62 const TInt KFilterFieldsSize = sizeof(KFilterFields) / sizeof(KFilterFields[0]); |
|
63 |
|
64 // Constants |
|
65 const TInt KLogBlockSize = 128; |
|
66 const TInt KLogPredicateListGranuality = 10; |
|
67 const TInt KLogMaxPredicateLength = 128; |
|
68 const TInt KLogNumberCharsToMatch = 9; |
|
69 |
|
70 /** |
|
71 Sets the iDatabase data member. |
|
72 The rest of the data member is left uninitialized. They will be initialized later by the BuildExprLC() call. |
|
73 @param aDatabase A reference to MLogServDatabaseTransactionInterface interface. |
|
74 */ |
|
75 TLogFilterExprBuilder::TLogFilterExprBuilder(MLogServDatabaseTransactionInterface& aDatabase) : |
|
76 iDatabase(aDatabase) |
|
77 { |
|
78 } |
|
79 |
|
80 /** |
|
81 Builds the WHERE expresssion of an SQL statement used later to filter events from the Event table. |
|
82 How the builder works? - BuildExprLC() gets as a parameter list of filters: CLogFilterList. |
|
83 Each filter is an object of CLogFilter type. The CLogFilter class contains the same set of properties as the CLogEvent |
|
84 class: phone number, SIM id, call type, etc. Some of the filter property values are set, defining the desired set |
|
85 of events that can pass the filter. |
|
86 |
|
87 For example, the filter list has two filters: |
|
88 - Filter 1: number is "1011", SimId is 200; |
|
89 - Filter 2: duration type is 2; |
|
90 |
|
91 BuildExprLC() takes the filter list and depending on passed TLogFilterConstructionType type: |
|
92 - ELogFilterConstructFilterByFilterFieldByField |
|
93 Organises two loops: the outer loop iterates over all field types, the inner loop iterates over the filters; |
|
94 - ELogFilterConstructFieldByFieldFilterByFilter |
|
95 Organises two loops: the outer loop iterates over the filters, the inner loop iterates over all field types; |
|
96 |
|
97 On each inner loop iteration the current field value of the filter will be checked and if it is not null then a predicate |
|
98 will be created of form "<column name> = <field value>" and added to the list of predicates. |
|
99 If the field value is null but it is allowed to include that field in the expression (the related bit of |
|
100 CLogFilter::iNullFields is set. This is tested by using CLogFilter::NullFields()), then the predicate format will be |
|
101 "<column name> IS NULL". |
|
102 So using the example filters above, the predicates lists will be: |
|
103 - "Number = '1011'", "SimId - 200"; |
|
104 - "DType = 2"; |
|
105 |
|
106 At the end of each outer loop iteration the predicates will be "linked" using either "AND" if the field type is "flags" |
|
107 or "OR" for the rest of the fields types. |
|
108 So, after the first outer loop iteration, the constructed part of the WHERE expression will be: |
|
109 "Number = '1011' OR SimId = 200". |
|
110 After the second outer loop iteration the expression will be: "DType = 2". |
|
111 Also, depending on the TLogFilterConstructionType type these expressions will be "linked" either by "AND" or "OR": |
|
112 "(Number = '1011' OR SimId = 200) AND (DType = 2)". |
|
113 |
|
114 On the first outer loop iteration, the predicates expression will be prefixed by the string refered by the aInitial |
|
115 parameter (that could be "WHERE " or " AND " or " OR "). |
|
116 |
|
117 When the processing of the filters finishes, the ready for use expression will be in the aExpr out parameter. |
|
118 |
|
119 @param aExpr Out parameter. If BuildExprLC() completes successfully, aExpr contrains the generated expression. |
|
120 The caller is responsible for the destruction of aExpr. BuildExprLC() will create aExpr and put it on |
|
121 the cleanup stack; |
|
122 aFilterList Filters list; |
|
123 aInitial String that has to be added in front of the generated expresssion; |
|
124 aType Defines the order of the processing of the filters and the fields; |
|
125 @leave KErrNoMemory Out of memory condition has occured. |
|
126 */ |
|
127 void TLogFilterExprBuilder::BuildExprLC(RLogDynBuf& aExpr, const CLogFilterList& aFilterList, const TDesC& aInitial, |
|
128 TLogFilterConstructionType aType) |
|
129 { |
|
130 aExpr.CreateLC(KLogBlockSize); |
|
131 iPredicateList = new (ELeave) CDesCArrayFlat(KLogPredicateListGranuality); |
|
132 CleanupStack::PushL(iPredicateList); |
|
133 |
|
134 iFilterList = &aFilterList; |
|
135 iInitial = &aInitial; |
|
136 iConstructionType = aType; |
|
137 iFilterIndex = 0; |
|
138 iField = KFilterFields[0]; |
|
139 iFlagIndex = 0; |
|
140 |
|
141 __LOGFILTQ_INVARIANT(); |
|
142 |
|
143 switch(iConstructionType) |
|
144 { |
|
145 case ELogFilterConstructFilterByFilterFieldByField: |
|
146 DoNextProcessFilterByFilterFieldByFieldL(aExpr); |
|
147 break; |
|
148 case ELogFilterConstructFieldByFieldFilterByFilter: |
|
149 DoNextProcessFieldByFieldFilterByFilterL(aExpr); |
|
150 break; |
|
151 default: |
|
152 __ASSERT_DEBUG(EFalse, Panic(ELogInvalidConstructionType)); |
|
153 break; |
|
154 } |
|
155 |
|
156 #ifdef _DEBUG |
|
157 iFilterList = NULL; |
|
158 iInitial = NULL; |
|
159 iFilterIndex = -1; |
|
160 iField = 0; |
|
161 iFlagIndex = -1; |
|
162 #endif |
|
163 CleanupStack::PopAndDestroy(iPredicateList); |
|
164 } |
|
165 |
|
166 /** |
|
167 Processes the filters and the fields. |
|
168 Organises two loops: |
|
169 - the outer loop is on the fields; |
|
170 - the inner loop is on the filters; |
|
171 |
|
172 @param aExpr Out parameter. The place where the expression is generated. |
|
173 @leave KErrNoMemory Out of memory condition has occured. |
|
174 |
|
175 @see BuildExprLC() |
|
176 */ |
|
177 void TLogFilterExprBuilder::DoNextProcessFilterByFilterFieldByFieldL(RLogDynBuf& aExpr) |
|
178 { |
|
179 __LOGFILTQ_INVARIANT(); |
|
180 const TInt KCount = iFilterList->Count(); |
|
181 for(TInt i=0;i<KFilterFieldsSize;++i) |
|
182 { |
|
183 iField = KFilterFields[i]; |
|
184 for(iFilterIndex=0; iFilterIndex<KCount; ++iFilterIndex) |
|
185 { |
|
186 iField != ELogFlagsField ? MakePredicatesL() : MakeFlagPredicatesL(); |
|
187 } |
|
188 MakeConditionL(aExpr); |
|
189 iPredicateList->Reset(); |
|
190 } |
|
191 } |
|
192 |
|
193 /** |
|
194 Processes the filters and the fields. |
|
195 Organises two loops: |
|
196 - the outer loop is on the filters; |
|
197 - the inner loop is on the fields; |
|
198 |
|
199 @param aExpr Out parameter. The place where the expression is generated. |
|
200 @leave KErrNoMemory Out of memory condition has occured. |
|
201 |
|
202 @see BuildExprLC() |
|
203 */ |
|
204 void TLogFilterExprBuilder::DoNextProcessFieldByFieldFilterByFilterL(RLogDynBuf& aExpr) |
|
205 { |
|
206 __LOGFILTQ_INVARIANT(); |
|
207 const TInt KCount = iFilterList->Count(); |
|
208 for(iFilterIndex=0; iFilterIndex<KCount; ++iFilterIndex) |
|
209 { |
|
210 //Process all filter fields except flags. |
|
211 for(TInt i=0;i<(KFilterFieldsSize-1);++i) |
|
212 { |
|
213 iField = KFilterFields[i]; |
|
214 MakePredicatesL(); |
|
215 } |
|
216 //Process the flag fields last |
|
217 iField = KFilterFields[KFilterFieldsSize - 1]; |
|
218 __ASSERT_DEBUG(iField == ELogFlagsField, User::Invariant()); |
|
219 MakeFlagPredicatesL(); |
|
220 MakeConditionL(aExpr); |
|
221 iPredicateList->Reset(); |
|
222 } |
|
223 } |
|
224 |
|
225 /** |
|
226 Called on each inner iteration from DoNextProcessFieldByFieldFilterByFilterL() and |
|
227 DoNextProcessFilterByFilterFieldByFieldL(). |
|
228 Generates a predicate in one of the following formats: |
|
229 - "<column name> = <field value>" |
|
230 - "<column name> IS NULL" |
|
231 The generated predicate will be added to the predicates list (iPredicateList data member). |
|
232 |
|
233 @leave KErrNoMemory Out of memory condition has occured. |
|
234 |
|
235 @see DoNextProcessFilterByFilterFieldByFieldL() |
|
236 @see DoNextProcessFieldByFieldFilterByFilterL() |
|
237 */ |
|
238 void TLogFilterExprBuilder::MakePredicatesL() |
|
239 { |
|
240 __LOGFILTQ_INVARIANT(); |
|
241 |
|
242 const CLogFilter* filter = iFilterList->At(iFilterIndex); |
|
243 __ASSERT_DEBUG(filter, Panic(ELogNullFilterInList1)); |
|
244 |
|
245 // Check for null field in filter and if the field has already been used |
|
246 TBuf<KLogMaxPredicateLength> predicate; |
|
247 if (!IsFieldEmpty(*filter) && !IsDuplicateField(*filter)) |
|
248 { |
|
249 MakePredicateL(predicate, *filter); |
|
250 if (predicate.Length() > 0) |
|
251 iPredicateList->AppendL(predicate); |
|
252 } |
|
253 |
|
254 // Add Null predicate if required and not already specified |
|
255 if (filter->NullFields() & iField && !IsDuplicateNullField()) |
|
256 { |
|
257 predicate.Zero(); |
|
258 MakeNullPredicate(predicate); |
|
259 if (predicate.Length() > 0) |
|
260 iPredicateList->AppendL(predicate); |
|
261 } |
|
262 |
|
263 __LOGFILTQ_INVARIANT(); |
|
264 } |
|
265 |
|
266 /** |
|
267 Called on each outer loop iteration. |
|
268 At this time, all generated predicates are in the predicates list (iPredicateList data member). |
|
269 The predicates will be "linked" into the expression using "AND" for the "flags" and "OR" for the rest of the fields. |
|
270 Depending on the TLogFilterConstructionType type (iConstructionType data member) either "AND" or "OR" will be used |
|
271 to "link" pedicates from two different predicates lists. |
|
272 |
|
273 @param aExpr Out parameter. The place where the expression is generated. |
|
274 @leave KErrNoMemory Out of memory condition has occured. |
|
275 |
|
276 @see DoNextProcessFilterByFilterFieldByFieldL() |
|
277 @see DoNextProcessFieldByFieldFilterByFilterL() |
|
278 @see MakePredicatesL() |
|
279 */ |
|
280 void TLogFilterExprBuilder::MakeConditionL(RLogDynBuf& aExpr) |
|
281 { |
|
282 __ASSERT_DEBUG(iFilterList != NULL, User::Invariant()); |
|
283 __ASSERT_DEBUG(iInitial != NULL, User::Invariant()); |
|
284 __ASSERT_DEBUG(iConstructionType == ELogFilterConstructFilterByFilterFieldByField || iConstructionType == ELogFilterConstructFieldByFieldFilterByFilter, User::Invariant()); |
|
285 __ASSERT_DEBUG(iPredicateList != NULL, User::Invariant()); |
|
286 |
|
287 // Are there any predicates to add? |
|
288 TInt total = iPredicateList->MdcaCount(); |
|
289 if (total == 0) |
|
290 return; |
|
291 |
|
292 // Add separator between conditions |
|
293 if(aExpr.Length() == 0) |
|
294 { |
|
295 aExpr.AppendL(*iInitial); |
|
296 } |
|
297 else |
|
298 { |
|
299 switch(iConstructionType) |
|
300 { |
|
301 case ELogFilterConstructFilterByFilterFieldByField: |
|
302 aExpr.AppendL(KLogAnd); |
|
303 break; |
|
304 case ELogFilterConstructFieldByFieldFilterByFilter: |
|
305 aExpr.AppendL(KLogOr); |
|
306 break; |
|
307 default: |
|
308 __ASSERT_DEBUG(EFalse, Panic(ELogInvalidConstructionType)); |
|
309 break; |
|
310 } |
|
311 } |
|
312 |
|
313 aExpr.AppendL(KLogOpenBracket); |
|
314 |
|
315 // Add Predicates |
|
316 TInt count = 0; |
|
317 while(count < total) |
|
318 { |
|
319 // Add separator between predicates |
|
320 if (count > 0) |
|
321 { |
|
322 if (iField != ELogFlagsField) |
|
323 aExpr.AppendL(KLogOr); |
|
324 else |
|
325 aExpr.AppendL(KLogAnd); |
|
326 } |
|
327 |
|
328 aExpr.AppendL((*iPredicateList)[count]); |
|
329 count++; |
|
330 } |
|
331 |
|
332 // Close the brackets |
|
333 aExpr.AppendL(KLogCloseBracket); |
|
334 } |
|
335 |
|
336 /** |
|
337 Called on each inner loop iteration. |
|
338 Processes the "flags" filter fields and generates predicates. |
|
339 |
|
340 @leave KErrNoMemory Out of memory condition has occured. |
|
341 |
|
342 @see DoNextProcessFilterByFilterFieldByFieldL() |
|
343 @see DoNextProcessFieldByFieldFilterByFilterL() |
|
344 */ |
|
345 void TLogFilterExprBuilder::MakeFlagPredicatesL() |
|
346 { |
|
347 __LOGFILTQ_INVARIANT(); |
|
348 |
|
349 const CLogFilter* filter = iFilterList->At(iFilterIndex); |
|
350 __ASSERT_DEBUG(filter, Panic(ELogNullFilterInList2)); |
|
351 |
|
352 // Return if no flags are set |
|
353 if (filter->Flags() == KLogNullFlags) |
|
354 return; |
|
355 |
|
356 TBuf<KLogMaxPredicateLength> predicate; |
|
357 |
|
358 // Go through each bit in turn |
|
359 iFlagIndex = KLogFlagsCount; |
|
360 while(iFlagIndex--) |
|
361 { |
|
362 // See if the current flag is set in filter and bit wasn't set in any previous filters |
|
363 if (filter->Flags() & 0x1 << iFlagIndex && !IsDuplicateField(*filter)) |
|
364 { |
|
365 // Generate predicate - if null field flag set we don't want the flag to be set |
|
366 predicate.Format(KLogFlagPredicate, &KLogFlagString, iFlagIndex + 1, (filter->NullFields() & iField) ? 0 : 1); |
|
367 iPredicateList->AppendL(predicate); |
|
368 } |
|
369 } |
|
370 iFlagIndex = 0; |
|
371 |
|
372 __LOGFILTQ_INVARIANT(); |
|
373 } |
|
374 |
|
375 /** |
|
376 Depending on the currently processed field (iField data member) the function returns the column name that |
|
377 has to be used in the predicate being generated. |
|
378 |
|
379 @return A const reference to the column name. |
|
380 |
|
381 @see MakeNullPredicate() |
|
382 @see MakePredicateL() |
|
383 */ |
|
384 const TDesC& TLogFilterExprBuilder::ColumnName() const |
|
385 { |
|
386 __LOGFILTQ_INVARIANT(); |
|
387 switch (iField) |
|
388 { |
|
389 case ELogContactField: |
|
390 return KLogFieldEventContactString(); |
|
391 case ELogDirectionField: |
|
392 return KLogFieldEventDirectionString(); |
|
393 case ELogDurationTypeField: |
|
394 return KLogFieldEventDTypeString(); |
|
395 case ELogEventTypeField: |
|
396 return KLogFieldEventTypeString(); |
|
397 case ELogNumberField: |
|
398 return KLogFieldEventNumberString(); |
|
399 case ELogRemotePartyField: |
|
400 return KLogFieldEventRemoteString(); |
|
401 case ELogStatusField: |
|
402 return KLogFieldEventStatusString(); |
|
403 case ELogSubjectField: |
|
404 return KLogFieldEventSubjectString(); |
|
405 case ELogLinkField: |
|
406 return KLogFieldEventLinkString(); |
|
407 case ELogDataField: |
|
408 return KLogFieldEventDataString(); |
|
409 case ELogStartTimeField: |
|
410 case ELogEndTimeField: |
|
411 return KLogFieldEventTimeString(); |
|
412 #ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM |
|
413 case ELogSimIdField: |
|
414 return KLogFieldEventSimId(); |
|
415 #endif |
|
416 default: |
|
417 __ASSERT_DEBUG(EFalse, Panic(ELogNoSuchState3)); |
|
418 break; |
|
419 } |
|
420 return KLogUnknownString(); |
|
421 } |
|
422 |
|
423 /** |
|
424 Generates a predicate of form "<column name> IS NULL" in the passed descriptor. |
|
425 |
|
426 @param aDes Out parameter. The place where the predicate will be generated. |
|
427 |
|
428 @see MakePredicatesL() |
|
429 */ |
|
430 void TLogFilterExprBuilder::MakeNullPredicate(TDes& aDes) |
|
431 { |
|
432 __LOGFILTQ_INVARIANT(); |
|
433 aDes.Format(KLogNullPredicate, &ColumnName()); |
|
434 __LOGFILTQ_INVARIANT(); |
|
435 } |
|
436 |
|
437 /** |
|
438 Generates a predicate of form "<column name> = <field value>" in the passed descriptor. |
|
439 |
|
440 @param aDes Out parameter. The place where the predicate will be generated. |
|
441 @param aFilter The filter where the field values will be picked from. |
|
442 The current field is identified by the value of the iField data member. |
|
443 |
|
444 @leave The leaving codes from TTime::FormatL(). |
|
445 |
|
446 @see MakePredicatesL() |
|
447 */ |
|
448 void TLogFilterExprBuilder::MakePredicateL(TDes& aDes, const CLogFilter& aFilter) |
|
449 { |
|
450 __LOGFILTQ_INVARIANT(); |
|
451 const TDesC& columnName = ColumnName(); |
|
452 switch (iField) |
|
453 { |
|
454 case ELogContactField: |
|
455 aDes.Format(KLogNumberPredicate, &columnName, aFilter.Contact()); |
|
456 break; |
|
457 |
|
458 case ELogDirectionField: |
|
459 { |
|
460 TLogStringId id = iDatabase.DTICacheStrings().FindId(aFilter.Direction()); |
|
461 aDes.Format(KLogNumberPredicate, &columnName, id); |
|
462 } |
|
463 break; |
|
464 |
|
465 case ELogDurationTypeField: |
|
466 aDes.Format(KLogNumberPredicate, &columnName, aFilter.DurationType()); |
|
467 break; |
|
468 |
|
469 case ELogEventTypeField: |
|
470 { |
|
471 const TLogServCacheTypeEntry& entry = iDatabase.DTICacheTypes().FindByUid(aFilter.EventType()); |
|
472 aDes.Format(KLogNumberPredicate, &columnName, entry.iEventTypeId); |
|
473 break; |
|
474 } |
|
475 |
|
476 // If the phone number in the filter is at least KLogNumberCharsToMatch long |
|
477 // then it does a wild card search for numbers that match the last KLogNumberCharsToMatch chars |
|
478 case ELogNumberField: |
|
479 { |
|
480 if (aFilter.Number().Length() < KLogNumberCharsToMatch) |
|
481 aDes.Format(KLogStringPredicate, &columnName, &aFilter.Number()); |
|
482 else |
|
483 { |
|
484 TPtrC number(aFilter.Number().Right(KLogNumberCharsToMatch)); |
|
485 aDes.Format(KLogLikePredicate, &columnName, &number); |
|
486 } |
|
487 break; |
|
488 } |
|
489 |
|
490 case ELogRemotePartyField: |
|
491 //We need to check RemoteParty string for any single quotes and |
|
492 //add a second single quote to properly handle strings such as |
|
493 //"Sam's Wife" |
|
494 { |
|
495 //If single quotes are found we need to modify the string |
|
496 TInt quoteIndex = aFilter.RemoteParty().Locate('\''); |
|
497 if( quoteIndex >= 0) |
|
498 { |
|
499 //Allocate a buffer twice the length of the string to cater for |
|
500 //the worst case when every character is a single quote |
|
501 TPtrC temp = aFilter.RemoteParty(); |
|
502 TBuf<KLogMaxRemotePartyLength * 2> buf; |
|
503 |
|
504 //loop through and replace all single quotes |
|
505 //with two quote characters |
|
506 while(quoteIndex >= 0) |
|
507 { |
|
508 _LIT(KQuoteStr, "''"); |
|
509 //Append the characters before the single quote followed |
|
510 //by two quote characters |
|
511 buf.Append(temp.Left(quoteIndex)); |
|
512 buf.Append(KQuoteStr); |
|
513 |
|
514 //Set the substring to the remaining characters after the |
|
515 //single quote and look for the next single quote character |
|
516 temp.Set(temp.Mid(quoteIndex + 1)); |
|
517 quoteIndex = temp.Locate('\''); |
|
518 } |
|
519 |
|
520 //No quotes left so append the remaining data |
|
521 buf.Append(temp); |
|
522 aDes.Format(KLogStringPredicate, &columnName, &buf); |
|
523 } |
|
524 else |
|
525 { |
|
526 aDes.Format(KLogStringPredicate, &columnName, &aFilter.RemoteParty()); |
|
527 } |
|
528 } |
|
529 break; |
|
530 |
|
531 case ELogStatusField: |
|
532 { |
|
533 TLogStringId id = iDatabase.DTICacheStrings().FindId(aFilter.Status()); |
|
534 aDes.Format(KLogNumberPredicate, &columnName, id); |
|
535 } |
|
536 break; |
|
537 |
|
538 case ELogStartTimeField: |
|
539 { |
|
540 TTime time = aFilter.StartTime(); |
|
541 TBuf<KLogMaxDateLength> buf; |
|
542 time.FormatL(buf, LogUtils::DateFormatForLocale()); |
|
543 aDes.Format(KLogDateAfterPredicate, &columnName, &buf); |
|
544 } |
|
545 break; |
|
546 |
|
547 case ELogEndTimeField: |
|
548 { |
|
549 TTime time = aFilter.EndTime(); |
|
550 TBuf<KLogMaxDateLength> buf; |
|
551 time.FormatL(buf, LogUtils::DateFormatForLocale()); |
|
552 aDes.Format(KLogDateBeforePredicate, &columnName, &buf); |
|
553 } |
|
554 break; |
|
555 |
|
556 #ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM |
|
557 case ELogSimIdField: |
|
558 aDes.Format(KLogUNumberPredicate, &columnName, aFilter.SimId()); |
|
559 break; |
|
560 #endif |
|
561 |
|
562 default: |
|
563 __ASSERT_DEBUG(EFalse, Panic(ELogNoSuchState4)); |
|
564 break; |
|
565 }; |
|
566 __LOGFILTQ_INVARIANT(); |
|
567 } |
|
568 |
|
569 /** |
|
570 Determines whether the current field identified by the value of the iField data member, is a duplicate, used/defined |
|
571 by the previously processed filters. For example, if there are two filters and both define the "number" field value, then |
|
572 only the "number" value from the first filter will be used. |
|
573 |
|
574 @param aFilter The current filter being processed; |
|
575 @return True the current field value has been already used in some of the previously processed filters, false otherwise. |
|
576 |
|
577 @see IsDuplicateNullField() |
|
578 @see MakePredicatesL() |
|
579 */ |
|
580 TBool TLogFilterExprBuilder::IsDuplicateField(const CLogFilter& aFilter) const |
|
581 { |
|
582 __LOGFILTQ_INVARIANT(); |
|
583 TInt count = iFilterIndex; |
|
584 while(count--) |
|
585 { |
|
586 const CLogFilter* testFilter = iFilterList->At(count); |
|
587 __ASSERT_DEBUG(testFilter, Panic(ELogNullFilterInList3)); |
|
588 if (IsDuplicate(aFilter, *testFilter)) |
|
589 return ETrue; |
|
590 } |
|
591 return EFalse; |
|
592 } |
|
593 |
|
594 /** |
|
595 Determines whether the current "null" field identified by the value of the iField data member, is a duplicate, used/defined |
|
596 by the previously processed filters. |
|
597 |
|
598 @param aFilter The current filter being processed; |
|
599 @return True the current "null" field value has been already used in some of the previously processed filters, false otherwise. |
|
600 |
|
601 @see IsDuplicateField() |
|
602 @see MakePredicatesL() |
|
603 */ |
|
604 TBool TLogFilterExprBuilder::IsDuplicateNullField() const |
|
605 { |
|
606 __LOGFILTQ_INVARIANT(); |
|
607 TInt count = iFilterIndex; |
|
608 while(count--) |
|
609 { |
|
610 const CLogFilter* testFilter = iFilterList->At(count); |
|
611 __ASSERT_DEBUG(testFilter, Panic(ELogNullFilterInList4)); |
|
612 if (testFilter->NullFields() & iField) |
|
613 return ETrue; |
|
614 } |
|
615 return EFalse; |
|
616 } |
|
617 |
|
618 /** |
|
619 Determines whether the current field value, identified by the value of the iField data member, is a null value. |
|
620 |
|
621 @param aFilter The current filter being processed; |
|
622 @return True The current field value is null, false otherwise. |
|
623 |
|
624 @see MakePredicatesL() |
|
625 */ |
|
626 TBool TLogFilterExprBuilder::IsFieldEmpty(const CLogFilter& aFilter) const |
|
627 { |
|
628 __LOGFILTQ_INVARIANT(); |
|
629 switch (iField) |
|
630 { |
|
631 case ELogContactField: |
|
632 return aFilter.Contact() == KLogNullContactId; |
|
633 |
|
634 case ELogDirectionField: |
|
635 return aFilter.Direction().Length() == 0; |
|
636 |
|
637 case ELogDurationTypeField: |
|
638 return aFilter.DurationType() == KLogNullDurationType; |
|
639 |
|
640 case ELogEventTypeField: |
|
641 return aFilter.EventType() == KNullUid; |
|
642 |
|
643 case ELogNumberField: |
|
644 return aFilter.Number().Length() == 0; |
|
645 |
|
646 case ELogRemotePartyField: |
|
647 return aFilter.RemoteParty().Length() == 0; |
|
648 |
|
649 case ELogStatusField: |
|
650 return aFilter.Status().Length() == 0; |
|
651 |
|
652 case ELogStartTimeField: |
|
653 return (aFilter.StartTime() == TTime(0)); |
|
654 |
|
655 case ELogEndTimeField: |
|
656 return (aFilter.EndTime() == TTime(0)); |
|
657 |
|
658 // These fields are not part of the filter |
|
659 case ELogSubjectField: |
|
660 case ELogLinkField: |
|
661 case ELogDataField: |
|
662 return ETrue; |
|
663 |
|
664 #ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM |
|
665 case ELogSimIdField: |
|
666 return (aFilter.SimId() == KLogNullSimId); |
|
667 #endif |
|
668 |
|
669 default: |
|
670 __ASSERT_DEBUG(EFalse, Panic(ELogNoSuchState5)); |
|
671 break; |
|
672 }; |
|
673 return ETrue; |
|
674 } |
|
675 |
|
676 /** |
|
677 The function checks whether the field identified by the value of the iField data member has the same value in the |
|
678 passed two filter objects. |
|
679 |
|
680 @param aFilter1 Filter 1 |
|
681 @param aFilter1 Filter 2 |
|
682 @return True The values of the current field are identical in both filters, false otherwise. |
|
683 |
|
684 @see IsDuplicateField() |
|
685 */ |
|
686 TBool TLogFilterExprBuilder::IsDuplicate(const CLogFilter& aFilter1, const CLogFilter& aFilter2) const |
|
687 { |
|
688 __LOGFILTQ_INVARIANT(); |
|
689 switch (iField) |
|
690 { |
|
691 case ELogContactField: |
|
692 return aFilter1.Contact() == aFilter2.Contact(); |
|
693 |
|
694 case ELogDirectionField: |
|
695 return aFilter1.Direction().CompareF(aFilter2.Direction()) == 0; |
|
696 |
|
697 case ELogDurationTypeField: |
|
698 return aFilter1.DurationType() == aFilter2.DurationType(); |
|
699 |
|
700 case ELogEventTypeField: |
|
701 return aFilter1.EventType() == aFilter2.EventType(); |
|
702 |
|
703 // The number fields in filters are considered to be duplicates if the last KLogNumberCharsToMatch chars match |
|
704 case ELogNumberField: |
|
705 { |
|
706 TPtrC number1(aFilter1.Number().Right(KLogNumberCharsToMatch)); |
|
707 TPtrC number2(aFilter2.Number().Right(KLogNumberCharsToMatch)); |
|
708 return number1.CompareF(number2) == 0; |
|
709 } |
|
710 |
|
711 case ELogRemotePartyField: |
|
712 return aFilter1.RemoteParty().CompareF(aFilter2.RemoteParty()) == 0; |
|
713 |
|
714 case ELogStatusField: |
|
715 return aFilter1.Status().CompareF(aFilter2.Status()) == 0; |
|
716 |
|
717 case ELogStartTimeField: |
|
718 return aFilter1.StartTime() == aFilter2.StartTime(); |
|
719 |
|
720 case ELogEndTimeField: |
|
721 return aFilter1.EndTime() == aFilter2.EndTime(); |
|
722 |
|
723 case ELogFlagsField: |
|
724 return aFilter2.Flags() & iFlagIndex; |
|
725 |
|
726 #ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM |
|
727 case ELogSimIdField: |
|
728 return aFilter1.SimId() == aFilter2.SimId(); |
|
729 #endif |
|
730 |
|
731 default: |
|
732 __ASSERT_DEBUG(EFalse, Panic(ELogNoSuchState6)); |
|
733 break; |
|
734 }; |
|
735 return EFalse; |
|
736 } |
|
737 |
|
738 #ifdef _DEBUG |
|
739 void TLogFilterExprBuilder::Invariant() const |
|
740 { |
|
741 __ASSERT_DEBUG(KFilterFields[KFilterFieldsSize - 1] == ELogFlagsField, User::Invariant()); |
|
742 __ASSERT_DEBUG(iFilterList != NULL, User::Invariant()); |
|
743 __ASSERT_DEBUG(iInitial != NULL, User::Invariant()); |
|
744 __ASSERT_DEBUG(iConstructionType == ELogFilterConstructFilterByFilterFieldByField || iConstructionType == ELogFilterConstructFieldByFieldFilterByFilter, User::Invariant()); |
|
745 __ASSERT_DEBUG((TUint)iFilterIndex < iFilterList->Count(), User::Invariant()); |
|
746 TInt idx = KMaxTInt; |
|
747 for(idx=0;idx<KFilterFieldsSize && iField!=KFilterFields[idx];++idx) |
|
748 { |
|
749 } |
|
750 __ASSERT_DEBUG(idx < KFilterFieldsSize, User::Invariant()); |
|
751 __ASSERT_DEBUG((iField & (iField - 1)) == 0, User::Invariant()); |
|
752 __ASSERT_DEBUG((TUint)iFlagIndex < KLogFlagsCount, User::Invariant()); |
|
753 __ASSERT_DEBUG(iPredicateList != NULL, User::Invariant()); |
|
754 } |
|
755 #endif |