loggingservices/eventlogger/LogServ/src/LOGFILTQ.CPP
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     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