os/persistentdata/loggingservices/eventlogger/LogServ/src/LOGFILTQ.CPP
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/loggingservices/eventlogger/LogServ/src/LOGFILTQ.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,755 @@
     1.4 +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include "LOGFILTQ.H"
    1.20 +#include <logcli.h>
    1.21 +#include <logcntdef.h>
    1.22 +#include "logservpanic.h"
    1.23 +#include "LogServDatabaseTransactionInterface.h"
    1.24 +#include <logfilterandeventconstants.hrh>
    1.25 +#include "LogServCacheStrings.h"
    1.26 +#include "LogServCacheTypes.h"
    1.27 +#include "LogServSqlStrings.h"
    1.28 +
    1.29 +#ifdef _DEBUG
    1.30 +#  define __LOGFILTQ_INVARIANT()  Invariant()
    1.31 +#else
    1.32 +#  define __LOGFILTQ_INVARIANT()  void(0)
    1.33 +#endif
    1.34 +
    1.35 +/**
    1.36 +KFilterFields array contains all fields that can participate in a filter.
    1.37 +The term "field" refers a constant, which value is power of two.
    1.38 +Every "field" uniquely identifies one of the event properties.
    1.39 +The field values are used in the implementation of the TLogFilterExprBuilder class for initializing the 
    1.40 +iField data member, used to identify the currently processed event property value.  
    1.41 +@internalComponent 
    1.42 +*/
    1.43 +const TUint16 KFilterFields[] = 
    1.44 +	{
    1.45 +	ELogContactField,
    1.46 +	ELogDirectionField,
    1.47 +	ELogDurationTypeField,
    1.48 +	ELogEventTypeField,
    1.49 +	ELogNumberField,
    1.50 +	ELogRemotePartyField,
    1.51 +	ELogStatusField,
    1.52 +	ELogStartTimeField,
    1.53 +	ELogEndTimeField,
    1.54 +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM	
    1.55 +	ELogSimIdField,		//The new ELogSimIdField must be before the flags: see 
    1.56 +						//DoNextProcessFieldByFieldFilterByFilterL() implementation and the assert.
    1.57 +#endif	
    1.58 +	ELogFlagsField
    1.59 +	};
    1.60 +
    1.61 +/**
    1.62 +The size of the KFilterFields array.
    1.63 +@internalComponent 
    1.64 +*/
    1.65 +const TInt KFilterFieldsSize = sizeof(KFilterFields) / sizeof(KFilterFields[0]);
    1.66 +
    1.67 +// Constants
    1.68 +const TInt KLogBlockSize = 128;
    1.69 +const TInt KLogPredicateListGranuality = 10;
    1.70 +const TInt KLogMaxPredicateLength = 128;
    1.71 +const TInt KLogNumberCharsToMatch = 9;
    1.72 +
    1.73 +/**
    1.74 +Sets the iDatabase data member.
    1.75 +The rest of the data member is left uninitialized. They will be initialized later by the BuildExprLC() call.
    1.76 +@param aDatabase A reference to MLogServDatabaseTransactionInterface interface.  
    1.77 +*/
    1.78 +TLogFilterExprBuilder::TLogFilterExprBuilder(MLogServDatabaseTransactionInterface& aDatabase) :
    1.79 +    iDatabase(aDatabase)
    1.80 +	{
    1.81 +	}
    1.82 +
    1.83 +/**
    1.84 +Builds the WHERE expresssion of an SQL statement used later to filter events from the Event table.
    1.85 +How the builder works? - BuildExprLC() gets as a parameter list of filters: CLogFilterList.
    1.86 +Each filter is an object of CLogFilter type. The CLogFilter class contains the same set of properties as the CLogEvent
    1.87 +class: phone number, SIM id, call type, etc. Some of the filter property values are set, defining the desired set
    1.88 +of events that can pass the filter.
    1.89 +
    1.90 +For example, the filter list has two filters:
    1.91 + - Filter 1: number is "1011", SimId is 200;
    1.92 + - Filter 2: duration type is 2;
    1.93 + 
    1.94 +BuildExprLC() takes the filter list and depending on passed TLogFilterConstructionType type:
    1.95 + - ELogFilterConstructFilterByFilterFieldByField
    1.96 +   Organises two loops: the outer loop iterates over all field types, the inner loop iterates over the filters;
    1.97 + - ELogFilterConstructFieldByFieldFilterByFilter  
    1.98 +   Organises two loops: the outer loop iterates over the filters, the inner loop iterates over all field types;
    1.99 +
   1.100 +On each inner loop iteration the current field value of the filter will be checked and if it is not null then a predicate 
   1.101 +will be created of form "<column name> = <field value>" and added to the list of predicates.
   1.102 +If the field value is null but it is allowed to include that field in the expression (the related bit of 
   1.103 +CLogFilter::iNullFields is set. This is tested by using CLogFilter::NullFields()), then the predicate format will be
   1.104 +"<column name> IS NULL".
   1.105 +So using the example filters above, the predicates lists will be:
   1.106 + - "Number = '1011'", "SimId - 200";
   1.107 + - "DType = 2";
   1.108 +
   1.109 +At the end of each outer loop iteration the predicates will be "linked" using either "AND" if the field type is "flags"
   1.110 +or "OR" for the rest of the fields types.
   1.111 +So, after the first outer loop iteration, the constructed part of the WHERE expression will be:
   1.112 + "Number = '1011' OR SimId = 200". 
   1.113 +After the second outer loop iteration the expression will be: "DType = 2".
   1.114 +Also, depending on the TLogFilterConstructionType type these expressions will be "linked" either by "AND" or "OR":
   1.115 + "(Number = '1011' OR SimId = 200) AND (DType = 2)".
   1.116 + 
   1.117 +On the first outer loop iteration, the predicates expression will be prefixed by the string refered by the aInitial
   1.118 +parameter (that could be "WHERE " or " AND " or " OR ").
   1.119 +
   1.120 +When the processing of the filters finishes, the ready for use expression will be in the aExpr out parameter.
   1.121 +
   1.122 +@param aExpr Out parameter. If BuildExprLC() completes successfully, aExpr contrains the generated expression.
   1.123 +             The caller is responsible for the destruction of aExpr. BuildExprLC() will create aExpr and put it on
   1.124 +             the cleanup stack; 
   1.125 +       aFilterList Filters list;
   1.126 +       aInitial String that has to be added in front of the generated expresssion;
   1.127 +       aType Defines the order of the processing of the filters and the fields;
   1.128 +@leave KErrNoMemory Out of memory condition has occured.             
   1.129 +*/
   1.130 +void TLogFilterExprBuilder::BuildExprLC(RLogDynBuf& aExpr, const CLogFilterList& aFilterList, const TDesC& aInitial, 
   1.131 +                                        TLogFilterConstructionType aType)
   1.132 +	{
   1.133 +	aExpr.CreateLC(KLogBlockSize);
   1.134 +    iPredicateList = new (ELeave) CDesCArrayFlat(KLogPredicateListGranuality);
   1.135 +    CleanupStack::PushL(iPredicateList);
   1.136 +
   1.137 +    iFilterList = &aFilterList;
   1.138 +    iInitial = &aInitial;
   1.139 +    iConstructionType = aType;
   1.140 +    iFilterIndex = 0;
   1.141 +    iField = KFilterFields[0];
   1.142 +    iFlagIndex = 0;
   1.143 +    
   1.144 +    __LOGFILTQ_INVARIANT();
   1.145 +    
   1.146 +    switch(iConstructionType)
   1.147 +        {
   1.148 +        case ELogFilterConstructFilterByFilterFieldByField:
   1.149 +            DoNextProcessFilterByFilterFieldByFieldL(aExpr);
   1.150 +            break;
   1.151 +        case ELogFilterConstructFieldByFieldFilterByFilter:
   1.152 +            DoNextProcessFieldByFieldFilterByFilterL(aExpr);
   1.153 +            break;
   1.154 +        default:
   1.155 +            __ASSERT_DEBUG(EFalse, Panic(ELogInvalidConstructionType));
   1.156 +            break;
   1.157 +        }
   1.158 +
   1.159 +#ifdef _DEBUG
   1.160 +    iFilterList = NULL;
   1.161 +    iInitial = NULL;
   1.162 +    iFilterIndex = -1;
   1.163 +    iField = 0;
   1.164 +    iFlagIndex = -1;
   1.165 +#endif    
   1.166 +    CleanupStack::PopAndDestroy(iPredicateList);
   1.167 +	}
   1.168 +
   1.169 +/**
   1.170 +Processes the filters and the fields.
   1.171 +Organises two loops:
   1.172 + - the outer loop is on the fields;
   1.173 + - the inner loop is on the filters; 
   1.174 +
   1.175 +@param aExpr Out parameter. The place where the expression is generated. 
   1.176 +@leave KErrNoMemory Out of memory condition has occured.             
   1.177 +
   1.178 +@see BuildExprLC() 
   1.179 +*/
   1.180 +void TLogFilterExprBuilder::DoNextProcessFilterByFilterFieldByFieldL(RLogDynBuf& aExpr)
   1.181 +	{
   1.182 +    __LOGFILTQ_INVARIANT();
   1.183 +	const TInt KCount = iFilterList->Count();
   1.184 +	for(TInt i=0;i<KFilterFieldsSize;++i)
   1.185 +	    {
   1.186 +	    iField = KFilterFields[i];
   1.187 +	    for(iFilterIndex=0; iFilterIndex<KCount; ++iFilterIndex)
   1.188 +	        {
   1.189 +	        iField != ELogFlagsField ? MakePredicatesL() : MakeFlagPredicatesL();  
   1.190 +	        }
   1.191 +        MakeConditionL(aExpr);
   1.192 +        iPredicateList->Reset();
   1.193 +	    }
   1.194 +	}
   1.195 +
   1.196 +/**
   1.197 +Processes the filters and the fields.
   1.198 +Organises two loops:
   1.199 + - the outer loop is on the filters; 
   1.200 + - the inner loop is on the fields;
   1.201 + 
   1.202 +@param aExpr Out parameter. The place where the expression is generated. 
   1.203 +@leave KErrNoMemory Out of memory condition has occured.             
   1.204 +
   1.205 +@see BuildExprLC() 
   1.206 +*/
   1.207 +void TLogFilterExprBuilder::DoNextProcessFieldByFieldFilterByFilterL(RLogDynBuf& aExpr)
   1.208 +	{
   1.209 +    __LOGFILTQ_INVARIANT();
   1.210 +    const TInt KCount = iFilterList->Count();
   1.211 +    for(iFilterIndex=0; iFilterIndex<KCount; ++iFilterIndex)
   1.212 +        {
   1.213 +        //Process all filter fields except flags.
   1.214 +    	for(TInt i=0;i<(KFilterFieldsSize-1);++i)
   1.215 +            {
   1.216 +    	    iField = KFilterFields[i];
   1.217 +            MakePredicatesL();
   1.218 +            }
   1.219 +    	//Process the flag fields last
   1.220 +	    iField = KFilterFields[KFilterFieldsSize - 1];
   1.221 +        __ASSERT_DEBUG(iField == ELogFlagsField, User::Invariant());
   1.222 +        MakeFlagPredicatesL();
   1.223 +        MakeConditionL(aExpr);
   1.224 +        iPredicateList->Reset();
   1.225 +        }
   1.226 +	}
   1.227 +
   1.228 +/**
   1.229 +Called on each inner iteration from DoNextProcessFieldByFieldFilterByFilterL() and 
   1.230 +DoNextProcessFilterByFilterFieldByFieldL().
   1.231 +Generates a predicate in one of the following formats:
   1.232 + - "<column name> = <field value>"
   1.233 + - "<column name> IS NULL"
   1.234 +The generated predicate will be added to the predicates list (iPredicateList data member).
   1.235 +
   1.236 +@leave KErrNoMemory Out of memory condition has occured.              
   1.237 +
   1.238 +@see DoNextProcessFilterByFilterFieldByFieldL()
   1.239 +@see DoNextProcessFieldByFieldFilterByFilterL()
   1.240 +*/
   1.241 +void TLogFilterExprBuilder::MakePredicatesL()
   1.242 +	{
   1.243 +    __LOGFILTQ_INVARIANT();
   1.244 +	
   1.245 +	const CLogFilter* filter = iFilterList->At(iFilterIndex);
   1.246 +	__ASSERT_DEBUG(filter, Panic(ELogNullFilterInList1));
   1.247 +
   1.248 +	// Check for null field in filter and if the field has already been used
   1.249 +	TBuf<KLogMaxPredicateLength> predicate;
   1.250 +	if (!IsFieldEmpty(*filter) && !IsDuplicateField(*filter))
   1.251 +		{
   1.252 +		MakePredicateL(predicate, *filter);
   1.253 +		if (predicate.Length() > 0)
   1.254 +			iPredicateList->AppendL(predicate);
   1.255 +		}
   1.256 +
   1.257 +	// Add Null predicate if required and not already specified
   1.258 +	if (filter->NullFields() & iField && !IsDuplicateNullField())
   1.259 +		{
   1.260 +		predicate.Zero();
   1.261 +		MakeNullPredicate(predicate);
   1.262 +		if (predicate.Length() > 0)
   1.263 +			iPredicateList->AppendL(predicate);
   1.264 +		}
   1.265 +
   1.266 +    __LOGFILTQ_INVARIANT();
   1.267 +	}
   1.268 +
   1.269 +/**
   1.270 +Called on each outer loop iteration.
   1.271 +At this time, all generated predicates are in the predicates list (iPredicateList data member).
   1.272 +The predicates will be "linked" into the expression using "AND" for the "flags" and "OR" for the rest of the fields.
   1.273 +Depending on the TLogFilterConstructionType type (iConstructionType data member) either "AND" or "OR" will be used 
   1.274 +to "link" pedicates from two different predicates lists.  
   1.275 +
   1.276 +@param aExpr Out parameter. The place where the expression is generated. 
   1.277 +@leave KErrNoMemory Out of memory condition has occured.
   1.278 +
   1.279 +@see DoNextProcessFilterByFilterFieldByFieldL()
   1.280 +@see DoNextProcessFieldByFieldFilterByFilterL()
   1.281 +@see MakePredicatesL()
   1.282 +*/
   1.283 +void TLogFilterExprBuilder::MakeConditionL(RLogDynBuf& aExpr)
   1.284 +	{
   1.285 +    __ASSERT_DEBUG(iFilterList != NULL, User::Invariant());
   1.286 +    __ASSERT_DEBUG(iInitial != NULL, User::Invariant());
   1.287 +    __ASSERT_DEBUG(iConstructionType == ELogFilterConstructFilterByFilterFieldByField || iConstructionType == ELogFilterConstructFieldByFieldFilterByFilter, User::Invariant());
   1.288 +    __ASSERT_DEBUG(iPredicateList != NULL, User::Invariant());
   1.289 +	
   1.290 +	// Are there any predicates to add?
   1.291 +	TInt total = iPredicateList->MdcaCount();
   1.292 +	if (total == 0)
   1.293 +		return;
   1.294 +
   1.295 +	// Add separator between conditions
   1.296 +	if(aExpr.Length() == 0)
   1.297 +	    {
   1.298 +	    aExpr.AppendL(*iInitial);
   1.299 +	    }
   1.300 +	else
   1.301 +		{
   1.302 +		switch(iConstructionType)
   1.303 +			{
   1.304 +		case ELogFilterConstructFilterByFilterFieldByField:
   1.305 +			aExpr.AppendL(KLogAnd);
   1.306 +			break;
   1.307 +		case ELogFilterConstructFieldByFieldFilterByFilter:
   1.308 +			aExpr.AppendL(KLogOr);
   1.309 +			break;
   1.310 +		default:
   1.311 +            __ASSERT_DEBUG(EFalse, Panic(ELogInvalidConstructionType));
   1.312 +		    break;
   1.313 +			}
   1.314 +		}
   1.315 +
   1.316 +	aExpr.AppendL(KLogOpenBracket);
   1.317 +
   1.318 +	// Add Predicates
   1.319 +	TInt count = 0;
   1.320 +	while(count < total)
   1.321 +		{
   1.322 +		// Add separator between predicates
   1.323 +		if (count > 0)
   1.324 +			{
   1.325 +			if (iField != ELogFlagsField)
   1.326 +				aExpr.AppendL(KLogOr);
   1.327 +			else
   1.328 +				aExpr.AppendL(KLogAnd);
   1.329 +			}
   1.330 +
   1.331 +		aExpr.AppendL((*iPredicateList)[count]);
   1.332 +		count++;
   1.333 +		}
   1.334 +
   1.335 +	// Close the brackets
   1.336 +	aExpr.AppendL(KLogCloseBracket);
   1.337 +	}
   1.338 +
   1.339 +/**
   1.340 +Called on each inner loop iteration.
   1.341 +Processes the "flags" filter fields and generates predicates.
   1.342 +
   1.343 +@leave KErrNoMemory Out of memory condition has occured.
   1.344 +
   1.345 +@see DoNextProcessFilterByFilterFieldByFieldL()
   1.346 +@see DoNextProcessFieldByFieldFilterByFilterL()
   1.347 +*/
   1.348 +void TLogFilterExprBuilder::MakeFlagPredicatesL()
   1.349 +    {
   1.350 +    __LOGFILTQ_INVARIANT();
   1.351 +    
   1.352 +    const CLogFilter* filter = iFilterList->At(iFilterIndex);
   1.353 +    __ASSERT_DEBUG(filter, Panic(ELogNullFilterInList2));
   1.354 +
   1.355 +    // Return if no flags are set
   1.356 +    if (filter->Flags() == KLogNullFlags)
   1.357 +        return;
   1.358 +
   1.359 +    TBuf<KLogMaxPredicateLength> predicate;
   1.360 +
   1.361 +    // Go through each bit in turn
   1.362 +    iFlagIndex = KLogFlagsCount;
   1.363 +    while(iFlagIndex--)
   1.364 +        {
   1.365 +        // See if the current flag is set in filter and bit wasn't set in any previous filters
   1.366 +        if (filter->Flags() & 0x1 << iFlagIndex && !IsDuplicateField(*filter))
   1.367 +            {
   1.368 +            // Generate predicate - if null field flag set we don't want the flag to be set
   1.369 +            predicate.Format(KLogFlagPredicate, &KLogFlagString, iFlagIndex + 1, (filter->NullFields() & iField) ? 0 : 1);
   1.370 +            iPredicateList->AppendL(predicate);
   1.371 +            }
   1.372 +        }
   1.373 +    iFlagIndex = 0;
   1.374 +    
   1.375 +    __LOGFILTQ_INVARIANT();
   1.376 +    }
   1.377 +
   1.378 +/**
   1.379 +Depending on the currently processed field (iField data member) the function returns the column name that
   1.380 +has to be used in the predicate being generated.
   1.381 +
   1.382 +@return A const reference to the column name.
   1.383 +
   1.384 +@see MakeNullPredicate()
   1.385 +@see MakePredicateL()   
   1.386 +*/
   1.387 +const TDesC& TLogFilterExprBuilder::ColumnName() const
   1.388 +	{
   1.389 +    __LOGFILTQ_INVARIANT();
   1.390 +	switch (iField)
   1.391 +		{
   1.392 +		case ELogContactField:
   1.393 +			return KLogFieldEventContactString();
   1.394 +		case ELogDirectionField:
   1.395 +			return KLogFieldEventDirectionString();
   1.396 +		case ELogDurationTypeField:
   1.397 +			return KLogFieldEventDTypeString();
   1.398 +		case ELogEventTypeField:
   1.399 +			return KLogFieldEventTypeString();
   1.400 +		case ELogNumberField:
   1.401 +			return KLogFieldEventNumberString();
   1.402 +		case ELogRemotePartyField:
   1.403 +			return KLogFieldEventRemoteString();
   1.404 +		case ELogStatusField:
   1.405 +			return KLogFieldEventStatusString();
   1.406 +		case ELogSubjectField:
   1.407 +			return KLogFieldEventSubjectString();
   1.408 +		case ELogLinkField:
   1.409 +			return KLogFieldEventLinkString();
   1.410 +		case ELogDataField:
   1.411 +			return KLogFieldEventDataString();
   1.412 +		case ELogStartTimeField:
   1.413 +		case ELogEndTimeField:
   1.414 +			return KLogFieldEventTimeString();
   1.415 +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM	
   1.416 +		case ELogSimIdField:
   1.417 +			return KLogFieldEventSimId();
   1.418 +#endif			
   1.419 +		default:
   1.420 +			__ASSERT_DEBUG(EFalse, Panic(ELogNoSuchState3));
   1.421 +			break;
   1.422 +		}
   1.423 +	return KLogUnknownString();
   1.424 +	}
   1.425 +
   1.426 +/**
   1.427 +Generates a predicate of form "<column name> IS NULL" in the passed descriptor.
   1.428 +
   1.429 +@param aDes Out parameter. The place where the predicate will be generated.
   1.430 +
   1.431 +@see MakePredicatesL() 
   1.432 +*/
   1.433 +void TLogFilterExprBuilder::MakeNullPredicate(TDes& aDes)
   1.434 +    {
   1.435 +    __LOGFILTQ_INVARIANT();
   1.436 +    aDes.Format(KLogNullPredicate, &ColumnName());
   1.437 +    __LOGFILTQ_INVARIANT();
   1.438 +    }
   1.439 +
   1.440 +/**
   1.441 +Generates a predicate of form "<column name> = <field value>" in the passed descriptor.
   1.442 +
   1.443 +@param aDes Out parameter. The place where the predicate will be generated.
   1.444 +@param aFilter The filter where the field values will be picked from.
   1.445 +               The current field is identified by the value of the iField data member.
   1.446 +
   1.447 +@leave The leaving codes from TTime::FormatL().
   1.448 +
   1.449 +@see MakePredicatesL() 
   1.450 +*/
   1.451 +void TLogFilterExprBuilder::MakePredicateL(TDes& aDes, const CLogFilter& aFilter)
   1.452 +	{
   1.453 +    __LOGFILTQ_INVARIANT();
   1.454 +	const TDesC& columnName = ColumnName();
   1.455 +	switch (iField)
   1.456 +		{
   1.457 +		case ELogContactField:
   1.458 +			aDes.Format(KLogNumberPredicate, &columnName, aFilter.Contact());
   1.459 +			break;
   1.460 +
   1.461 +		case ELogDirectionField:
   1.462 +			{
   1.463 +			TLogStringId id = iDatabase.DTICacheStrings().FindId(aFilter.Direction());
   1.464 +			aDes.Format(KLogNumberPredicate, &columnName, id);
   1.465 +			}
   1.466 +			break;
   1.467 +
   1.468 +		case ELogDurationTypeField:
   1.469 +			aDes.Format(KLogNumberPredicate, &columnName, aFilter.DurationType());
   1.470 +			break;
   1.471 +
   1.472 +		case ELogEventTypeField:
   1.473 +			{
   1.474 +			const TLogServCacheTypeEntry& entry = iDatabase.DTICacheTypes().FindByUid(aFilter.EventType());
   1.475 +			aDes.Format(KLogNumberPredicate, &columnName, entry.iEventTypeId);
   1.476 +			break;
   1.477 +			}
   1.478 +
   1.479 +		// If the phone number in the filter is at least KLogNumberCharsToMatch long
   1.480 +		// then it does a wild card search for numbers that match the last KLogNumberCharsToMatch chars
   1.481 +		case ELogNumberField:
   1.482 +			{
   1.483 +			if (aFilter.Number().Length() < KLogNumberCharsToMatch)
   1.484 +				aDes.Format(KLogStringPredicate, &columnName, &aFilter.Number());
   1.485 +			else
   1.486 +				{
   1.487 +				TPtrC number(aFilter.Number().Right(KLogNumberCharsToMatch));
   1.488 +				aDes.Format(KLogLikePredicate, &columnName, &number);
   1.489 +				}
   1.490 +			break;
   1.491 +			}
   1.492 +
   1.493 +		case ELogRemotePartyField:
   1.494 +			//We need to check RemoteParty string for any single quotes and 
   1.495 +			//add a second single quote to properly handle strings such as 
   1.496 +			//"Sam's Wife"	
   1.497 +		    {
   1.498 +			//If single quotes are found we need to modify the string
   1.499 +			TInt quoteIndex =  aFilter.RemoteParty().Locate('\'');			
   1.500 +			if( quoteIndex >= 0)
   1.501 +				{	
   1.502 +				//Allocate a buffer twice the length of the string to cater for 
   1.503 +				//the worst case when every character is a single quote
   1.504 +				TPtrC temp = aFilter.RemoteParty();
   1.505 +				TBuf<KLogMaxRemotePartyLength * 2> buf;
   1.506 +
   1.507 +				//loop through and replace all single quotes
   1.508 +				//with two quote characters
   1.509 +				while(quoteIndex >= 0)
   1.510 +					{	
   1.511 +					_LIT(KQuoteStr, "''");
   1.512 +					//Append the characters before the single quote followed
   1.513 +					//by two quote characters
   1.514 +					buf.Append(temp.Left(quoteIndex));	
   1.515 +					buf.Append(KQuoteStr);
   1.516 +
   1.517 +					//Set the substring to the remaining characters after the
   1.518 +					//single quote and look for the next single quote character
   1.519 +					temp.Set(temp.Mid(quoteIndex + 1));
   1.520 +					quoteIndex = temp.Locate('\'');
   1.521 +					}		
   1.522 +
   1.523 +				//No quotes left so append the remaining data
   1.524 +				buf.Append(temp);
   1.525 +				aDes.Format(KLogStringPredicate, &columnName, &buf);
   1.526 +				}
   1.527 +			else
   1.528 +				{
   1.529 +				aDes.Format(KLogStringPredicate, &columnName, &aFilter.RemoteParty());
   1.530 +				}
   1.531 +		    }
   1.532 +			break;
   1.533 +
   1.534 +		case ELogStatusField:
   1.535 +			{
   1.536 +			TLogStringId id = iDatabase.DTICacheStrings().FindId(aFilter.Status());
   1.537 +			aDes.Format(KLogNumberPredicate, &columnName, id);
   1.538 +			}
   1.539 +			break;
   1.540 +			
   1.541 +		case ELogStartTimeField:
   1.542 +		    {
   1.543 +			TTime time = aFilter.StartTime();
   1.544 +		    TBuf<KLogMaxDateLength> buf;
   1.545 +			time.FormatL(buf, LogUtils::DateFormatForLocale());
   1.546 +			aDes.Format(KLogDateAfterPredicate, &columnName, &buf);
   1.547 +		    }
   1.548 +			break;  
   1.549 +
   1.550 +		case ELogEndTimeField:
   1.551 +		    {
   1.552 +			TTime time = aFilter.EndTime();
   1.553 +		    TBuf<KLogMaxDateLength> buf;
   1.554 +			time.FormatL(buf, LogUtils::DateFormatForLocale());
   1.555 +			aDes.Format(KLogDateBeforePredicate, &columnName, &buf);
   1.556 +		    }
   1.557 +			break;
   1.558 +			
   1.559 +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM	
   1.560 +		case ELogSimIdField:
   1.561 +			aDes.Format(KLogUNumberPredicate, &columnName, aFilter.SimId());
   1.562 +			break;
   1.563 +#endif	
   1.564 +			
   1.565 +		default:
   1.566 +			__ASSERT_DEBUG(EFalse, Panic(ELogNoSuchState4));
   1.567 +			break;
   1.568 +		};
   1.569 +    __LOGFILTQ_INVARIANT();
   1.570 +	}
   1.571 +
   1.572 +/**
   1.573 +Determines whether the current field identified by the value of the iField data member, is a duplicate, used/defined
   1.574 +by the previously processed filters. For example, if there are two filters and both define the "number" field value, then
   1.575 +only the "number" value from the first filter will be used.
   1.576 +
   1.577 +@param aFilter The current filter being processed;
   1.578 +@return True the current field value has been already used in some of the previously processed filters, false otherwise.
   1.579 +
   1.580 +@see IsDuplicateNullField()
   1.581 +@see MakePredicatesL() 
   1.582 +*/
   1.583 +TBool TLogFilterExprBuilder::IsDuplicateField(const CLogFilter& aFilter) const
   1.584 +    {
   1.585 +    __LOGFILTQ_INVARIANT();
   1.586 +    TInt count = iFilterIndex;
   1.587 +    while(count--)
   1.588 +        {
   1.589 +        const CLogFilter* testFilter = iFilterList->At(count);
   1.590 +        __ASSERT_DEBUG(testFilter, Panic(ELogNullFilterInList3));
   1.591 +        if (IsDuplicate(aFilter, *testFilter))
   1.592 +            return ETrue;
   1.593 +        }
   1.594 +    return EFalse;
   1.595 +    }
   1.596 +
   1.597 +/**
   1.598 +Determines whether the current "null" field identified by the value of the iField data member, is a duplicate, used/defined
   1.599 +by the previously processed filters.
   1.600 +
   1.601 +@param aFilter The current filter being processed;
   1.602 +@return True the current "null" field value has been already used in some of the previously processed filters, false otherwise.
   1.603 +
   1.604 +@see IsDuplicateField()
   1.605 +@see MakePredicatesL() 
   1.606 +*/
   1.607 +TBool TLogFilterExprBuilder::IsDuplicateNullField() const
   1.608 +    {
   1.609 +    __LOGFILTQ_INVARIANT();
   1.610 +    TInt count = iFilterIndex;
   1.611 +    while(count--)
   1.612 +        {
   1.613 +        const CLogFilter* testFilter = iFilterList->At(count);
   1.614 +        __ASSERT_DEBUG(testFilter, Panic(ELogNullFilterInList4));
   1.615 +        if (testFilter->NullFields() & iField)
   1.616 +            return ETrue;
   1.617 +        }
   1.618 +    return EFalse;  
   1.619 +    }
   1.620 +
   1.621 +/**
   1.622 +Determines whether the current field value, identified by the value of the iField data member, is a null value.
   1.623 +
   1.624 +@param aFilter The current filter being processed;
   1.625 +@return True The current field value is null, false otherwise.
   1.626 +
   1.627 +@see MakePredicatesL()  
   1.628 +*/
   1.629 +TBool TLogFilterExprBuilder::IsFieldEmpty(const CLogFilter& aFilter) const
   1.630 +	{
   1.631 +    __LOGFILTQ_INVARIANT();
   1.632 +	switch (iField)
   1.633 +		{
   1.634 +		case ELogContactField:
   1.635 +			return aFilter.Contact() == KLogNullContactId;
   1.636 +
   1.637 +		case ELogDirectionField:
   1.638 +			return aFilter.Direction().Length() == 0;
   1.639 +
   1.640 +		case ELogDurationTypeField:
   1.641 +			return aFilter.DurationType() == KLogNullDurationType;
   1.642 +
   1.643 +		case ELogEventTypeField:
   1.644 +			return aFilter.EventType() == KNullUid;
   1.645 +
   1.646 +		case ELogNumberField:
   1.647 +			return aFilter.Number().Length() == 0;
   1.648 +
   1.649 +		case ELogRemotePartyField:
   1.650 +			return aFilter.RemoteParty().Length() == 0;
   1.651 +
   1.652 +		case ELogStatusField:
   1.653 +			return aFilter.Status().Length() == 0;
   1.654 +
   1.655 +		case ELogStartTimeField:
   1.656 +			return (aFilter.StartTime() == TTime(0));
   1.657 +
   1.658 +		case ELogEndTimeField:
   1.659 +			return (aFilter.EndTime() == TTime(0));
   1.660 +
   1.661 +		// These fields are not part of the filter
   1.662 +		case ELogSubjectField:
   1.663 +		case ELogLinkField:
   1.664 +		case ELogDataField:
   1.665 +			return ETrue;
   1.666 +
   1.667 +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM	
   1.668 +		case ELogSimIdField:
   1.669 +			return (aFilter.SimId() == KLogNullSimId);
   1.670 +#endif
   1.671 +			
   1.672 +		default:
   1.673 +			__ASSERT_DEBUG(EFalse, Panic(ELogNoSuchState5));
   1.674 +			break;
   1.675 +		};
   1.676 +	return ETrue;
   1.677 +	}
   1.678 +
   1.679 +/**
   1.680 +The function checks whether the field identified by the value of the iField data member has the same value in the
   1.681 +passed two filter objects. 
   1.682 +
   1.683 +@param  aFilter1 Filter 1
   1.684 +@param  aFilter1 Filter 2
   1.685 +@return True The values of the current field are identical in both filters, false otherwise. 
   1.686 + 
   1.687 +@see IsDuplicateField() 
   1.688 +*/
   1.689 +TBool TLogFilterExprBuilder::IsDuplicate(const CLogFilter& aFilter1, const CLogFilter& aFilter2) const
   1.690 +	{
   1.691 +	__LOGFILTQ_INVARIANT();
   1.692 +	switch (iField)
   1.693 +		{
   1.694 +		case ELogContactField:
   1.695 +			return aFilter1.Contact() == aFilter2.Contact();
   1.696 +
   1.697 +		case ELogDirectionField:
   1.698 +			return aFilter1.Direction().CompareF(aFilter2.Direction()) == 0;
   1.699 +
   1.700 +		case ELogDurationTypeField:
   1.701 +			return aFilter1.DurationType() == aFilter2.DurationType();
   1.702 +
   1.703 +		case ELogEventTypeField:
   1.704 +			return aFilter1.EventType() == aFilter2.EventType();
   1.705 +
   1.706 +		// The number fields in filters are considered to be duplicates if the last KLogNumberCharsToMatch chars match
   1.707 +		case ELogNumberField:
   1.708 +			{
   1.709 +			TPtrC number1(aFilter1.Number().Right(KLogNumberCharsToMatch));
   1.710 +			TPtrC number2(aFilter2.Number().Right(KLogNumberCharsToMatch));
   1.711 +			return number1.CompareF(number2) == 0;
   1.712 +			}
   1.713 +
   1.714 +		case ELogRemotePartyField:
   1.715 +			return aFilter1.RemoteParty().CompareF(aFilter2.RemoteParty()) == 0;
   1.716 +
   1.717 +		case ELogStatusField:
   1.718 +			return aFilter1.Status().CompareF(aFilter2.Status()) == 0;
   1.719 +
   1.720 +		case ELogStartTimeField:
   1.721 +			return aFilter1.StartTime() == aFilter2.StartTime();
   1.722 +
   1.723 +		case ELogEndTimeField:
   1.724 +			return aFilter1.EndTime() == aFilter2.EndTime();
   1.725 +
   1.726 +		case ELogFlagsField:
   1.727 +			return aFilter2.Flags() & iFlagIndex;
   1.728 +
   1.729 +#ifdef SYMBIAN_ENABLE_EVENTLOGGER_DUALSIM	
   1.730 +		case ELogSimIdField:
   1.731 +			return aFilter1.SimId() == aFilter2.SimId();
   1.732 +#endif			
   1.733 +			
   1.734 +		default:
   1.735 +			__ASSERT_DEBUG(EFalse, Panic(ELogNoSuchState6));
   1.736 +			break;
   1.737 +		};
   1.738 +	return EFalse;
   1.739 +	}
   1.740 +
   1.741 +#ifdef _DEBUG
   1.742 +void TLogFilterExprBuilder::Invariant() const
   1.743 +    {
   1.744 +    __ASSERT_DEBUG(KFilterFields[KFilterFieldsSize - 1] == ELogFlagsField, User::Invariant());
   1.745 +    __ASSERT_DEBUG(iFilterList != NULL, User::Invariant());
   1.746 +    __ASSERT_DEBUG(iInitial != NULL, User::Invariant());
   1.747 +    __ASSERT_DEBUG(iConstructionType == ELogFilterConstructFilterByFilterFieldByField || iConstructionType == ELogFilterConstructFieldByFieldFilterByFilter, User::Invariant());
   1.748 +    __ASSERT_DEBUG((TUint)iFilterIndex < iFilterList->Count(), User::Invariant());
   1.749 +    TInt idx = KMaxTInt;
   1.750 +    for(idx=0;idx<KFilterFieldsSize && iField!=KFilterFields[idx];++idx)
   1.751 +    	{
   1.752 +    	}
   1.753 +    __ASSERT_DEBUG(idx < KFilterFieldsSize, User::Invariant());
   1.754 +    __ASSERT_DEBUG((iField & (iField - 1)) == 0, User::Invariant());
   1.755 +    __ASSERT_DEBUG((TUint)iFlagIndex < KLogFlagsCount, User::Invariant());
   1.756 +    __ASSERT_DEBUG(iPredicateList != NULL, User::Invariant());
   1.757 +    }
   1.758 +#endif