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