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