metadataengine/server/src/mdsnotifycomparator.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 15 Mar 2010 12:42:24 +0200
branchRCL_3
changeset 7 3cebc1a84278
parent 2 b73a2e62868f
child 20 f23c07ec56e2
permissions -rw-r--r--
Revision: 201009 Kit: 201010

/*
* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Comparator algorithms for notifier*
*/

#include "mdsnotifycomparator.h"

#include "mdcresult.h"
#include "mdcitem.h"
#include "mdccommon.pan"
#include "mdcserializationbuffer.h"
#include "mderange.h"
#include "mdscommoninternal.h"
#include "mdcquery.h"
#include "mdccommon.h"
#include "mdeinternalerror.h"

CMdSNotifyComparator* CMdSNotifyComparator::NewL()
    {
    CMdSNotifyComparator* that = CMdSNotifyComparator::NewLC();
    CleanupStack::Pop( that );
    return that;
    }

CMdSNotifyComparator* CMdSNotifyComparator::NewLC()
	{
	CMdSNotifyComparator* that = new(ELeave) CMdSNotifyComparator();
	CleanupStack::PushL( that );
	that->ConstructL();
	return that;
	}


CMdSNotifyComparator::~CMdSNotifyComparator()
    {
    
    }

CMdSNotifyComparator::CMdSNotifyComparator()
    {
    
    }

void CMdSNotifyComparator::ConstructL()
    {
    }

TBool CMdSNotifyComparator::MatchL(
	TDefId aNamespaceDefId, TUint32 aType,
    CMdCSerializationBuffer& aSerializedCondition,
    CMdCSerializationBuffer& aSerializedItems,
    CMdCSerializationBuffer& aSerializedItemIds,
    RArray<TItemId>& aMatchingItemIdArray,
    RArray<TItemId>& aAllItemsIdArray,
    RPointerArray<HBufC>& aMatchingItemUriArray,
    RPointerArray<HBufC>& aAllItemsUriArray,
    TBool aAllowConfidential,
    TBool uriNotify,
    TBool& aAllMatched,
    TBool& aAllItemsFetched )
    {
    const TMdCItems& items = TMdCItems::GetFromBufferL( aSerializedItems );

    const TMdCItemIds& itemIds = TMdCItemIds::GetFromBufferL( aSerializedItemIds );

	// check if some namespace definitions are not the same
    if( itemIds.iNamespaceDefId != aNamespaceDefId )
    	{
    	return EFalse;
    	}

    aAllMatched = EFalse;
    
    if( ( items.iObjects.iPtr.iCount > 0 ) && 
    	( itemIds.iObjectIds.iPtr.iCount > 0 ) && 
    	( aType & ( EObjectNotifyAdd | EObjectNotifyModify | EObjectNotifyAddWithUri | EObjectNotifyModifyWithUri ) ) )
    	{
    	// object ID count and object item count should match
		__ASSERT_DEBUG( items.iObjects.iPtr.iCount == itemIds.iObjectIds.iPtr.iCount, MMdCCommon::Panic( KErrCorrupt ) );

    	aSerializedItemIds.PositionL( itemIds.iObjectIds.iPtr.iOffset );
    	TBool allItemsFetched( aAllItemsFetched );
    	for( TUint32 i = 0; i < itemIds.iObjectIds.iPtr.iCount; i++ )
    		{
    		TItemId objectId;
    		aSerializedItemIds.ReceiveL( objectId );

    		if( aSerializedCondition.Size() > 0 )
    			{
	            TBool results( EFalse );
	            TBool succeed( EFalse );
    			
	            // move condition buffer's position beginnig of the buffer
	            aSerializedCondition.PositionL( KNoOffset  );
	            
	            const TMdCLogicCondition& logicCondition = 
	            		TMdCLogicCondition::GetFromBufferL( aSerializedCondition );

	            for ( TUint32 j = 0; j < logicCondition.iChildConditions.iPtr.iCount; j++ )
	                {
		    		// set correct position to item buffer
	    	    	aSerializedItems.PositionL( items.iObjects.iPtr.iOffset + 
	    	    			i * sizeof(TMdCObject) );

	    	    	// set correct positin to condition buffer
	    	    	aSerializedCondition.PositionL( 
	    	    			logicCondition.iChildConditions.iPtr.iOffset + 
	    	    			j * CMdCSerializationBuffer::KRequiredSizeForTUint32 );
	    	    	TUint32 conditionOffset;
	    	    	aSerializedCondition.ReceiveL( conditionOffset );
	    	    	aSerializedCondition.PositionL( conditionOffset );

	                results = MatchObjectL( aSerializedCondition, 
	                		aSerializedItems, objectId, aAllowConfidential );

	                succeed = results;
	                if ( logicCondition.iOperator == ELogicConditionOperatorAnd )
	                    {
	                    if( !results )
	                        {
	                        break;
	                        }
	                    }

	                if ( logicCondition.iOperator == ELogicConditionOperatorOr )
	                    {
	                    if( results )
	                        {
	                        break;
	                        }
	                    }
	                }
    		
	            if ( logicCondition.iNegated )    
	                {
	                succeed = !( succeed );
	                }

	    	    if ( succeed )    
	                {
	                if( uriNotify )
	                    {
	                    // set correct position to item buffer
	                    aSerializedItems.PositionL( items.iObjects.iPtr.iOffset + 
	                               i * sizeof(TMdCObject) );
	                    
	                   const TMdCObject& object = TMdCObject::GetFromBufferL( aSerializedItems );

	                    aSerializedItems.PositionL( object.iUri.iPtr.iOffset );
	                    HBufC* uriBuf = aSerializedItems.ReceiveDes16L();
	                    aMatchingItemUriArray.AppendL( uriBuf );
	                    }
	                aMatchingItemIdArray.AppendL( objectId );
	                }
    			}
    		else
    			{
                aAllMatched = ETrue;		
                if( uriNotify && (!aAllItemsFetched || !allItemsFetched) )
                    {
                    // set correct position to item buffer
                    aSerializedItems.PositionL( items.iObjects.iPtr.iOffset + 
                               i * sizeof(TMdCObject) );
                    
                   const TMdCObject& object = TMdCObject::GetFromBufferL( aSerializedItems );

                    aSerializedItems.PositionL( object.iUri.iPtr.iOffset );
                    HBufC* uriBuf = aSerializedItems.ReceiveDes16L();
                    aAllItemsUriArray.AppendL( uriBuf );
                    aAllItemsIdArray.AppendL( objectId );
                    allItemsFetched = ETrue;
                    }
                else if( !aAllItemsFetched || !allItemsFetched )
                    {
                    aAllItemsIdArray.AppendL( objectId );
                    allItemsFetched = ETrue;
                    }
                }
    		}
    	if( allItemsFetched )
    	    {
    	    aAllItemsFetched = ETrue;
    		}
    	}
    else if( ( items.iEvents.iPtr.iCount > 0 ) && 
    		 ( itemIds.iEventIds.iPtr.iCount > 0 ) && 
    		 ( aType & ( EEventNotifyAdd ) ) )
    	{
    	// event ID count and event item count should match
		__ASSERT_DEBUG( items.iEvents.iPtr.iCount == itemIds.iEventIds.iPtr.iCount, MMdCCommon::Panic( KErrCorrupt ) );

		aSerializedItemIds.PositionL( itemIds.iEventIds.iPtr.iOffset );
    	for( TUint32 i = 0; i < itemIds.iEventIds.iPtr.iCount; i++ )
    		{
    		TItemId eventId;
    		aSerializedItemIds.ReceiveL( eventId );
    		
    		if( aSerializedCondition.Size() > 0 )
    			{
	    		// set correct position to item buffer
	    		aSerializedItems.PositionL( items.iEvents.iPtr.iOffset + i * sizeof(TMdCEvent) );

	    		// move condition buffer's position to the begin of the buffer
	    		aSerializedCondition.PositionL( KNoOffset );

	    		if( MatchEventL( aSerializedCondition, aSerializedItems, eventId ) )
	    			{
	    			aMatchingItemIdArray.AppendL( eventId );
	    			}
    			}
    		else
    			{
    			aMatchingItemIdArray.AppendL( eventId );
    			}
    		}
    	}
    else if( ( items.iRelations.iPtr.iCount > 0 ) && 
    		 ( itemIds.iRelationIds.iPtr.iCount > 0 ) && 
    		 ( aType & ( ERelationNotifyAdd | ERelationNotifyModify ) ) )
    	{
    	// relation ID count and relation item count should match
		__ASSERT_DEBUG( items.iRelations.iPtr.iCount == itemIds.iRelationIds.iPtr.iCount, MMdCCommon::Panic( KErrCorrupt ) );

    	aSerializedItemIds.PositionL( itemIds.iRelationIds.iPtr.iOffset );
    	for( TUint32 i = 0; i < itemIds.iRelationIds.iPtr.iCount; i++ )
    		{
    		TItemId relationId;
    		aSerializedItemIds.ReceiveL( relationId );

			if( aSerializedCondition.Size() > 0 )
				{
	    		// set correct position to item buffer
	    		aSerializedItems.PositionL( items.iRelations.iPtr.iOffset
	    				+ i * sizeof(TMdCRelation) );

	    		// move condition buffer's position to the begin of the buffer
	    		aSerializedCondition.PositionL( KNoOffset );

	    		if( MatchRelationL( aSerializedCondition, aSerializedItems, relationId ) )
	    			{
	    			aMatchingItemIdArray.AppendL( relationId );
	    			}
				}
			else
				{
				aMatchingItemIdArray.AppendL( relationId );
				}
    		}
    	}

    if( aMatchingItemIdArray.Count() > 0 || ( aAllItemsIdArray.Count() > 0 && aAllMatched ))
    	{
    	return ETrue;
    	}
    else
    	{
    	return EFalse;
    	}
    }

TBool CMdSNotifyComparator::MatchObjectL(
		CMdCSerializationBuffer& aSerializedCondition,
		CMdCSerializationBuffer& aSerializedItem, TItemId aObjectId, 
		TBool aAllowConfidential )
	{
 	// check if object is failed
	if( aObjectId == KNoId )
		{
		return EFalse;
		}

	// Check type
	const TMdCCondition& condition = 
			TMdCCondition::GetFromBufferL( aSerializedCondition );

	switch( condition.iConditionType )
		{
	    case EConditionTypeObject:
	        {
	    	return ( CheckObjectL( aSerializedCondition, aSerializedItem, 
	    			aAllowConfidential ) );
	    	}
		case EConditionTypeProperty:
		case EConditionTypePropertyIntRange:
		case EConditionTypePropertyInt64Range:
		case EConditionTypePropertyUintRange:
		case EConditionTypePropertyRealRange:
		case EConditionTypePropertyTimeRange:
	    case EConditionTypePropertyText:
    	case EConditionTypePropertyBool:
	        {
   			return ( CheckPropertyL( aSerializedCondition, aSerializedItem ) );
	    	}
    	default:
#ifdef _DEBUG
    		User::Panic( _L("MdSNCMaO") , KErrMdEUnknownConditionType );
#endif    		
    	    break;
		}

	return EFalse;
	}

TBool CMdSNotifyComparator::CheckPropertyL( 
		CMdCSerializationBuffer& aSerializedCondition,
    	CMdCSerializationBuffer& aSerializedItem )
    {
    const TMdCObject& object = TMdCObject::GetFromBufferL( aSerializedItem );
    
    const TMdCPropertyCondition& propertyCondition = 
    		TMdCPropertyCondition::GetFromBufferL( aSerializedCondition );

    for( TUint32 i=0; i < object.iProperties.iPtr.iCount; i++ )
        {
        aSerializedItem.PositionL( object.iProperties.iPtr.iOffset
        		+ i * sizeof(TMdCProperty) );
        const TMdCProperty& property = TMdCProperty::GetFromBufferL( aSerializedItem );

        // check propertyDefId doesn't match -> skip it
        if( property.iPropertyDefId == propertyCondition.iPropertyDefId )
            {
            // move condition buffer to begin of the condition
            aSerializedCondition.PositionL( propertyCondition.iCondition );

            switch( propertyCondition.iConditionType )
	            {
	            case EConditionTypeProperty:
	            	{
		            // check only if existing condition is negated
	            	if( propertyCondition.iNegated )
	            		{
	            		return EFalse;
	            		}
	            	else
	            		{
	            		return ETrue;
	            		}
	            	}
	            
   	            case EConditionTypePropertyIntRange:
	                {
		            TInt32 rangeType32( 0 );
		            aSerializedCondition.ReceiveL( rangeType32 );
		            const TMdERangeType rangeType = ( TMdERangeType )rangeType32;

		            TMdCValueUnion minValue;
                    aSerializedCondition.ReceiveL( minValue );
                    TMdCValueUnion maxValue;
                    aSerializedCondition.ReceiveL( maxValue );

		            // init range for next test
                    TMdEIntRange range( minValue.iInt32, maxValue.iInt32, 
                    		rangeType );
		            
   	                if( range.InRange( property.iValue.iInt32 ) == propertyCondition.iNegated )
                        {
                        return EFalse;
                        }   
	                break;
	                }
	            case EConditionTypePropertyInt64Range:
	                {
		            TInt32 rangeType32( 0 );
		            aSerializedCondition.ReceiveL( rangeType32 );
		            const TMdERangeType rangeType = ( TMdERangeType )rangeType32;

		            TMdCValueUnion minValue;
                    aSerializedCondition.ReceiveL( minValue );
                    TMdCValueUnion maxValue;
                    aSerializedCondition.ReceiveL( maxValue );

                    // init range for next test
                    TMdEInt64Range range( minValue.iInt64, maxValue.iInt64, 
                    		rangeType );
                    
                    // test if valueType is in the range
                    if( range.InRange( property.iValue.iInt64 ) == propertyCondition.iNegated )
                        {
                        return EFalse;
                        }	                
	                break;
	                }
	            case EConditionTypePropertyUintRange:
	                {
		            TInt32 rangeType32( 0 );
		            aSerializedCondition.ReceiveL( rangeType32 );
		            const TMdERangeType rangeType = ( TMdERangeType )rangeType32;

		            TMdCValueUnion minValue;
                    aSerializedCondition.ReceiveL( minValue );
                    TMdCValueUnion maxValue;
                    aSerializedCondition.ReceiveL( maxValue );

                    // init range for next test
                    TMdEUintRange range( minValue.iUint32, maxValue.iUint32, 
                    		rangeType );
	               
   	                if( range.InRange( property.iValue.iUint32 ) == propertyCondition.iNegated )
                        {
                        return EFalse;
                        }   
	                break;
	                }
	            case EConditionTypePropertyRealRange:
	                {
		            TInt32 rangeType32( 0 );
		            aSerializedCondition.ReceiveL( rangeType32 );
		            const TMdERangeType rangeType = ( TMdERangeType )rangeType32;

		            TMdCValueUnion minValue;
                    aSerializedCondition.ReceiveL( minValue );
                    TMdCValueUnion maxValue;
                    aSerializedCondition.ReceiveL( maxValue );
                    
                    // init range for next test
                    TMdERealRange range( minValue.iReal, maxValue.iReal, rangeType );

                    // test if valueType is in the range
                    if( range.InRange( property.iValue.iReal ) == propertyCondition.iNegated )
                        {
                        return EFalse;
                        }	                
	                break;
	                }
	            case EConditionTypePropertyTimeRange:
                    {
		            TInt32 rangeType32( 0 );
		            aSerializedCondition.ReceiveL( rangeType32 );
		            TMdERangeType rangeType = ( TMdERangeType )rangeType32;

		            TMdCValueUnion minValue;
                    aSerializedCondition.ReceiveL( minValue );
                    TMdCValueUnion maxValue;
                    aSerializedCondition.ReceiveL( maxValue );

                    // init range for next test
                    TMdETimeRange range( minValue.iInt64, maxValue.iInt64, 
                    		rangeType );

	                TTime value( property.iValue.iInt64 );
                    // test if valueType is in the range
                    if( range.InRange( property.iValue.iInt64 ) == propertyCondition.iNegated )
                        {
                        return EFalse;
                        }	                
                    break;
                    }
                case EConditionTypePropertyText:
	                {
	                // SerializedItem
	                aSerializedItem.PositionL( property.iValue.iPtr.iOffset );
	                TPtrC16 value = aSerializedItem.ReceivePtr16L();

	                // ConditionItem
	                TUint32 condCompareMethod( 0 );
	                aSerializedCondition.ReceiveL( condCompareMethod );
	                TPtrC16 condValue = aSerializedCondition.ReceivePtr16L();

                    //Check, that compare method is in range
#ifdef _DEBUG
	                if( condCompareMethod <= ETextPropertyConditionCompareFirst || condCompareMethod >= ETextPropertyConditionCompareLast )
	                	{
						User::Panic( _L("MdSNCCP1") , KErrMdEUnknownConditionCompareMethod );
	                	}
#endif
	                TBool compareResult( EFalse );

	                switch( condCompareMethod )
		                {
	                    case ETextPropertyConditionCompareEquals:
	   		                {
	   		                if( (value == condValue ) )
	   		                    {
	   		                    compareResult = EFalse;
	   		                    }
	   		                break;
	   		                }
	                    case ETextPropertyConditionCompareContains:
	   		                {
	   		                compareResult = FindDes( value, condValue ); 
	   		                break;
	   		                }
	                    case ETextPropertyConditionCompareBeginsWith:
	   		                {
	   		                compareResult = CompareDesBeginsWith( value, condValue ); 
                            break;	   		               
	   		                }
	                    case ETextPropertyConditionCompareEndsWith:
	                        {
	   		                compareResult = CompareDesEndsWith( value, condValue );
                            break;	   		               
	   		                }
                        default: 
                            {
#ifdef _DEBUG
                            User::Panic( _L("MdSNCCP2") , KErrMdEUnknownConditionCompareMethod );
#endif
   		                    }
		                }          
	                
	                if( compareResult == propertyCondition.iNegated )
	                    {
	                    return EFalse;
	                    }
	                break;
	                }
	            case EConditionTypePropertyBool:
    		        {
			        const TBool value( property.iValue.iInt32 );

			        TBool condValue( EFalse );
			        aSerializedCondition.ReceiveL( condValue );

			        if( ( value == condValue ) == propertyCondition.iNegated )
				        {
				        return EFalse;
				        }
			        break;
    		        }
	            default:
	            	{
#ifdef _DEBUG
                    User::Panic( _L("MdSNCCP3") , KErrMdEUnknownConditionType );
#endif
	            	User::Leave( KErrMdEUnknownConditionType );
	            	}
	            } // switch

            return ETrue;

            } // if

        } // for

    return EFalse;
    }

TBool CMdSNotifyComparator::CheckObjectL( CMdCSerializationBuffer& aSerializedCondition,
    			   						  CMdCSerializationBuffer& aSerializedItem,
    			   						  TBool aAllowConfidential )
    {
    const TMdCObject& object = TMdCObject::GetFromBufferL( aSerializedItem );

	const TBool confidential = object.iFlags & EMdEObjectFlagConfidential;

	// check if object is confidential and confidentials are not allowed
	if( confidential && ( aAllowConfidential == EFalse ) )
		{
		return EFalse;
		}

	// check if no condition defined
	if( aSerializedCondition.Size() <= 0 )
		{
		// pass all successful objects
		return ETrue;
		}

	const TMdCObjectCondition& condition = 
			TMdCObjectCondition::GetFromBufferL( aSerializedCondition );

	switch( condition.iConfidentialityLevel )
		{
	    case EObjectConditionLevelNormal:
	    	if( confidential )
	    		{
	    		return EFalse;
	    		}
			break;
		case EObjectConditionLevelConfidential:
	    	if( confidential == EFalse )
	    		{
	    		return EFalse;
	    		}
			break;

	    default:
	    	{
#ifdef _DEBUG
            User::Panic( _L("MdSNCCO1") , KErrMdEUnknownConfidentialityLevel );
#endif	    	
	    	User::Leave( KErrMdEUnknownConfidentialityLevel );
	    	}
		}

	if( ( condition.iFlags & EMdEObjectFlagPlaceholder ) && 
			( object.iFlags & EMdEObjectFlagPlaceholder ) )
		{
		return EFalse;
		}

	// move position to begin of sub condition
	aSerializedCondition.PositionL( condition.iCondition );
	
	switch( condition.iCompareMethod )
		{
		case EObjectConditionCompareNone:
			break;

		case EObjectConditionCompareId:
			{
			TItemId conditionObjectId;
			aSerializedCondition.ReceiveL( conditionObjectId );

			if( ( conditionObjectId == object.iId ) == condition.iNegated )
				{
				return EFalse;
				}
			}
			break;

        case EObjectConditionCompareUsageCount:
			{
			TInt32 rangeType32;
			aSerializedCondition.ReceiveL( rangeType32 );
			const TMdERangeType rangeType = (TMdERangeType)rangeType32;

			TMdCValueUnion minValue;
			aSerializedCondition.ReceiveL( minValue );
			TMdCValueUnion maxValue;
			aSerializedCondition.ReceiveL( maxValue );

			// init range for next test
			TMdEUintRange range( minValue.iUint32, maxValue.iUint32, 
					rangeType );

			// test if event's creation time is in the range
			if( BoolEqual( range.InRange( object.iUsageCount ), condition.iNegated ) )
				{
				return EFalse;
				}
			}
			break;

		case EObjectConditionCompareGuid:
			{
			TInt64 conditionGuidHigh;
			aSerializedCondition.ReceiveL( conditionGuidHigh );
			TInt64 conditionGuidLow;
			aSerializedCondition.ReceiveL( conditionGuidLow );

			if( ( ( conditionGuidHigh == object.iGuidHigh ) && 
				( conditionGuidLow == object.iGuidLow ) ) == 
				condition.iNegated )
				{
				return EFalse;
				}
			}
			break;

        case EObjectConditionCompareObjectDef:
			{
			TDefId conditionObjectDefId;
			aSerializedCondition.ReceiveL( conditionObjectDefId );

			if( ( conditionObjectDefId == object.iDefId ) == condition.iNegated )
				{
				return EFalse;
				}
			}
			break;

        case EObjectConditionCompareUri:
			{
			aSerializedItem.PositionL( object.iUri.iPtr.iOffset );
			TPtrC16 uri = aSerializedItem.ReceivePtr16L();

			TPtrC16 conditionUri = aSerializedCondition.ReceivePtr16L();

			if( ( conditionUri.Compare( uri ) == 0 ) == condition.iNegated )
				{
				return EFalse;
				}
			}
			break;

        case EObjectConditionCompareUriBeginsWith:
			{
			aSerializedItem.PositionL( object.iUri.iPtr.iOffset );
			TPtrC16 uri = aSerializedItem.ReceivePtr16L();

			TPtrC16 conditionUri = aSerializedCondition.ReceivePtr16L();

			if( CompareDesBeginsWith( uri, conditionUri ) == condition.iNegated )
				{
				return EFalse;
				}
			}
			break;

	    default:
	    	{
#ifdef _DEBUG
            User::Panic( _L("MdSNCCO2") , KErrMdEUnknownConditionCompareMethod );
#endif	    	
	    	User::Leave( KErrMdEUnknownConditionCompareMethod );
	    	}
		}

	return ETrue;
    }


TBool CMdSNotifyComparator::MatchEventL(CMdCSerializationBuffer& aSerializedCondition,
					    			    CMdCSerializationBuffer& aSerializedItem,
					    			    TItemId aEventId)
	{
	const TMdCEvent& event = TMdCEvent::GetFromBufferL( aSerializedItem );

	// check if event is failed
	if( aEventId == 0 )
		{
		return EFalse;
		}

	// check if no condition defined
	if( aSerializedCondition.Size() <= 0 )
		{
		// pass all successful events
		return ETrue;
		}

	const TMdCEventCondition& eventCondition = 
			TMdCEventCondition::GetFromBufferL( aSerializedCondition );

	// check if event condition contains event ID comparsion
	if( eventCondition.iEventId != KNoId )
		{
		if( ( eventCondition.iEventId == event.iId ) == eventCondition.iNegated )
			{
			return EFalse;
			}
		}

	// check if event condition contains event def ID comparsion
	if( eventCondition.iEventDefId != KNoDefId )
		{
		if( ( eventCondition.iEventDefId == event.iDefId ) == eventCondition.iNegated )
			{
			return EFalse;
			}
		}

	// check event condition contains event creation time range comparision
	if( eventCondition.iCreationTimeRange != KNoOffset )
		{
		aSerializedCondition.PositionL( eventCondition.iCreationTimeRange );

		TInt32 rangeType32;
		aSerializedCondition.ReceiveL( rangeType32 );
		const TMdERangeType rangeType = (TMdERangeType)rangeType32;

		TMdCValueUnion minValue;
		aSerializedCondition.ReceiveL( minValue );
		TMdCValueUnion maxValue;
		aSerializedCondition.ReceiveL( maxValue );

		// init range for next test
		TMdEInt64Range range( minValue.iInt64, maxValue.iInt64, rangeType );

		// test if event's creation time is in the range
		if( range.InRange( event.iTime.Int64() ) == eventCondition.iNegated )
			{
			return EFalse;
			}
		}

	// check object condition 
	// (only accept OR-logic condition which contains object ID condition(s))
	if( eventCondition.iObjectCondition != KNoOffset )
		{
		aSerializedCondition.PositionL( eventCondition.iObjectCondition );

		if( MatchObjectIdToObjectIdConditionsL( aSerializedCondition, 
				event.iObjectId ) == eventCondition.iNegated )
			{
			return EFalse;
			}
		}

	// check event condition contains source or participant comparsion
	if( ( EEventConditionCompareSourceURI == eventCondition.iCompareMethod ) || 
		( EEventConditionCompareParticipantURI == eventCondition.iCompareMethod ) )
		{
		aSerializedCondition.PositionL( eventCondition.iUriCondition );

		TPtrC16 eventConditionUri = aSerializedCondition.ReceivePtr16L();

		// source comparsion
		if( EEventConditionCompareSourceURI == eventCondition.iCompareMethod )
			{
			TPtrC16 eventSource( KNullDesC );
			if ( event.iSourceText.iPtr.iCount > 0 )
				{
				aSerializedItem.PositionL( event.iSourceText.iPtr.iOffset );
				eventSource.Set( aSerializedItem.ReceivePtr16L() );
				}

			if( ( eventConditionUri.Compare( eventSource ) == 0 ) == eventCondition.iNegated )
				{
				return EFalse;
				}
			}
		// participant comparsion
		else
			{
			TPtrC16 eventParticipant( KNullDesC );
			if (event.iParticipantText.iPtr.iCount > 0)
				{
				aSerializedItem.PositionL( event.iParticipantText.iPtr.iOffset );
				eventParticipant.Set( aSerializedItem.ReceivePtr16L() );
				}

			if( ( eventConditionUri.Compare( eventParticipant ) == 0 ) == eventCondition.iNegated )
				{
				return EFalse;
				}
			}
		}

	return ETrue;
	}

TBool CMdSNotifyComparator::MatchRelationL(CMdCSerializationBuffer& aSerializedCondition,
    				 					   CMdCSerializationBuffer& aSerializedItem,
    				 					   TItemId aRelationId)
	{
    const TMdCRelation& relation = 
    		TMdCRelation::GetFromBufferL( aSerializedItem );

	// check if event is failed
	if( aRelationId == 0 )
		{
		return EFalse;
		}

	// check if no condition defined
	if( aSerializedCondition.Size() <= 0 )
		{
		// pass all successful events
		return ETrue;
		}

	const TMdCRelationCondition& relationCondition = 
			TMdCRelationCondition::GetFromBufferL( aSerializedCondition );

	// check if relation condition contains relation def ID comparsion
	if( relationCondition.iRelationDefId != KNoDefId &&
		BoolEqual( relationCondition.iRelationDefId == relation.iDefId, 
				relationCondition.iNegated ) )
		{
		return EFalse;
		}

	if ( relationCondition.iRelationId != KNoId &&
		 	 BoolEqual( relationCondition.iRelationId == aRelationId, 
		 			 relationCondition.iNegated ) )
		{
		return EFalse;
		}
	
	if ( relationCondition.iRelationIds.iPtr.iOffset != KNoOffset &&
			BoolEqual( MatchRelationIdsL( relationCondition, 
					aSerializedCondition, aRelationId ), 
					relationCondition.iNegated ) )
		{
		return EFalse;
		}

	if( relationCondition.iGuid != KNoOffset )
		{
		TInt64 conditionGuidHigh;
		aSerializedCondition.ReceiveL( conditionGuidHigh );
		TInt64 conditionGuidLow;
		aSerializedCondition.ReceiveL( conditionGuidLow );

		if ( conditionGuidHigh != 0 && conditionGuidLow != 0 &&
			 ( BoolEqual( conditionGuidHigh == relation.iGuidHigh, 
					 relationCondition.iNegated ) ||
			   BoolEqual( conditionGuidHigh == relation.iGuidLow, 
					   relationCondition.iNegated ) ) )
			{
			return EFalse;
			}
		}

	// check relation condition contains relation parameter range comparision
	if( relation.iParameter != KNoOffset )
		{
		aSerializedCondition.PositionL( relation.iParameter );
		
		TInt32 rangeType32;
		aSerializedCondition.ReceiveL( rangeType32 );
		const TMdERangeType rangeType = (TMdERangeType)rangeType32;

		TMdCValueUnion minValue;
		aSerializedCondition.ReceiveL( minValue );
		TMdCValueUnion maxValue;
		aSerializedCondition.ReceiveL( maxValue );

		// init range for next test
		TMdEIntRange range( minValue.iInt32, maxValue.iInt32, rangeType );

		// test if event's creation time is in the range
		if( BoolEqual( range.InRange( relation.iParameter ), 
				relationCondition.iNegated ) )
			{
			return EFalse;
			}
		}

	if( relationCondition.iLeftObjectCondition != KNoOffset && 
			ERelationConditionSideLeft == relationCondition.iObjectSide )
		{
		aSerializedCondition.PositionL( relationCondition.iLeftObjectCondition );

		if( BoolEqual( MatchObjectIdToObjectIdConditionsL(
				aSerializedCondition, relation.iLeftObjectId ), 
				relationCondition.iNegated ) )
			{
			return EFalse;
			}
		}

	if( relationCondition.iRightObjectCondition != KNoOffset && 
			ERelationConditionSideRight  == relationCondition.iObjectSide )
		{
		aSerializedCondition.PositionL( 
				relationCondition.iRightObjectCondition );

		if( BoolEqual( MatchObjectIdToObjectIdConditionsL(
				aSerializedCondition, relation.iRightObjectId ), 
				relationCondition.iNegated ) )
			{
			return EFalse;
			}
		}

	if ( ( relationCondition.iLeftObjectCondition != KNoOffset || 
			relationCondition.iRightObjectCondition != KNoOffset ) && 
			ERelationConditionSideEither == relationCondition.iObjectSide )
		{
		TBool eitherMatches = EFalse;
		
		if ( relationCondition.iLeftObjectCondition != KNoOffset )
			{
			aSerializedCondition.PositionL( 
					relationCondition.iLeftObjectCondition );
	
			if( !BoolEqual( MatchObjectIdToObjectIdConditionsL(
					aSerializedCondition, relation.iLeftObjectId ), 
					relationCondition.iNegated ) )
				{
				eitherMatches = ETrue;
				}
			}
		
		if ( relationCondition.iRightObjectCondition != KNoOffset )
			{
			aSerializedCondition.PositionL( 
					relationCondition.iRightObjectCondition );

			if( !BoolEqual( MatchObjectIdToObjectIdConditionsL(
					aSerializedCondition, relation.iRightObjectId ), 
					relationCondition.iNegated ) )
				{
				eitherMatches = ETrue;
				}
			}

		// left and right condition didn't match
		if( !eitherMatches )
			{
			return EFalse;
			}
		}

	if ( relationCondition.iLastModifiedDateRange != KNoOffset )
		{
		aSerializedCondition.PositionL( 
				relationCondition.iLastModifiedDateRange );

		TInt32 rangeRule;
		aSerializedCondition.ReceiveL( rangeRule );
		const TMdERangeType rangeType = (TMdERangeType)rangeRule;

		TMdCValueUnion minValue;
		aSerializedCondition.ReceiveL( minValue );
		TMdCValueUnion maxValue;
		aSerializedCondition.ReceiveL( maxValue );

		// init range for next test
		TMdEInt64Range range( minValue.iInt64, maxValue.iInt64, rangeType );

		// test if event's creation time is in the range
		if( BoolEqual( range.InRange( relation.iLastModifiedDate.Int64() ), 
				relationCondition.iNegated ) )
			{
			return EFalse;
			}
		}

	return ETrue;
	}

TBool CMdSNotifyComparator::MatchObjectIdsL(
						    CMdCSerializationBuffer& aSerializedCondition,
						    const RArray<TItemId>& aItemIdArray,
						    RArray<TItemId>& aMatchingItemIdArray
						    )
	{
	// check if condition buffer contains condition
	if( aSerializedCondition.Size() > 0 )
		{
		aSerializedCondition.PositionL( KNoOffset );

		const TMdCLogicCondition& logicCondition = 
				TMdCLogicCondition::GetFromBufferL( aSerializedCondition );

		for( TUint32 i = 0; i < logicCondition.iChildConditions.iPtr.iCount; i++ )
		    {
	       	aSerializedCondition.PositionL( 
	       			logicCondition.iChildConditions.iPtr.iOffset + 
	       			i * CMdCSerializationBuffer::KRequiredSizeForTUint32 );

	 		TUint32 childOffset;
		    aSerializedCondition.ReceiveL( childOffset );
		    aSerializedCondition.PositionL( childOffset );

		    const TMdCCondition& condition = TMdCCondition::GetFromBufferL( 
					aSerializedCondition );
			
			if( EConditionTypeObject == condition.iConditionType )
				{
				const TMdCObjectCondition& objectCondition = 
						TMdCObjectCondition::GetFromBufferL( aSerializedCondition );

			    if ( EObjectConditionCompareNone == objectCondition.iCompareMethod )
			    	{
                    // all matches
                    return ETrue;
			    	}
			    
	    		// only ID conditions are checked
	    		if( EObjectConditionCompareId == objectCondition.iCompareMethod )
	    			{
	    			aSerializedCondition.PositionL( objectCondition.iCondition );
	    			
	    			// get object condition's object ID
	    			TItemId conditionObjectId;
	    			aSerializedCondition.ReceiveL( conditionObjectId );

	    			const TInt objectIdCount = aItemIdArray.Count();
	    			for( TInt i = 0; i < objectIdCount; i++ )
	    				{
	    				const TItemId objectId = aItemIdArray[i];
	
	    				if( ( objectId == conditionObjectId ) != objectCondition.iNegated )
	    					{
	    					aMatchingItemIdArray.AppendL( objectId );
	    					}
	    				}
	
	    			if( aMatchingItemIdArray.Count() < aItemIdArray.Count() )
	    				{
	    				// none or some matches
	    				return EFalse;
	    				}	
	    			else
	    				{
	    				// all matches
	    				return ETrue;
	    				}
	    			}
	    		else
	    			{
                    // if condition is something else than ID, return true so that client receives
                    // needed notification even though also extra notifications will  be received
                    return ETrue;
	    			}
				}
    		}
		}
   return ETrue;
   }

TBool CMdSNotifyComparator::FindDes( TDesC16& aDes, TDesC16& aFindDes )
	{
	if( aDes.Find( aFindDes ) != KErrNotFound  )
	    {
	    return ETrue;
	    }
	return EFalse;
	}

TBool CMdSNotifyComparator::CompareDesEndsWith( TDesC16& aDes, TDesC16& aCompareDes )
	{
	if( aDes.Length() < aCompareDes.Length() )
		{
		return EFalse;
		}

	return ( aDes.Right( aCompareDes.Length() ).Compare( aCompareDes ) == 0 );
	}

TBool CMdSNotifyComparator::CompareDesBeginsWith( TDesC16& aDes, TDesC16& aCompareDes )
	{
	if( aDes.Length() < aCompareDes.Length() )
		{
		return EFalse;
		}

	return ( aDes.Left( aCompareDes.Length() ).Compare( aCompareDes ) == 0 );
	}

TBool CMdSNotifyComparator::MatchObjectIdToObjectIdConditionsL(
	CMdCSerializationBuffer& aSerializedCondition, TItemId aObjectId)
	{
	const TMdCLogicCondition& logicCondition = 
			TMdCLogicCondition::GetFromBufferL( aSerializedCondition );
	
	TBool matchingId = EFalse;

	for( TUint32 i = 0; i < logicCondition.iChildConditions.iPtr.iCount; i++ )
		{
		aSerializedCondition.PositionL( 
				logicCondition.iChildConditions.iPtr.iOffset + 
				i * CMdCSerializationBuffer::KRequiredSizeForTUint32 );

		TUint32 childOffset;
		aSerializedCondition.ReceiveL( childOffset );
		aSerializedCondition.PositionL( childOffset );

		const TMdCCondition& condition = TMdCCondition::GetFromBufferL( 
				aSerializedCondition );
		
		if( EConditionTypeObject == condition.iConditionType )
			{
			const TMdCObjectCondition& objectCondition = 
					TMdCObjectCondition::GetFromBufferL( aSerializedCondition );
			
			if( EObjectConditionCompareId == objectCondition.iCompareMethod )
				{
				aSerializedCondition.PositionL( objectCondition.iCondition );

				TItemId conditionObjectId;
				aSerializedCondition.ReceiveL( conditionObjectId );
				
				TBool currentMatch = ( conditionObjectId == aObjectId ) != objectCondition.iNegated;
	
				if( currentMatch )
					{
					matchingId = ETrue;
					break;
					}
				}
			}
		}
		
	return matchingId != logicCondition.iNegated;
	}

TBool CMdSNotifyComparator::MatchRelationIdsL(
		const TMdCRelationCondition& aRelationCondition, 
		CMdCSerializationBuffer& aSerializedCondition, TItemId aRelationId)
	{
	if( aRelationCondition.iRelationIds.iPtr.iCount > 0 &&
			aRelationCondition.iRelationIds.iPtr.iOffset != KNoOffset )
		{
		aSerializedCondition.PositionL( aRelationCondition.iRelationIds.iPtr.iOffset );

		for (TInt i = 0; i < aRelationCondition.iRelationIds.iPtr.iCount; ++i)
			{
			TItemId relationId;
			aSerializedCondition.ReceiveL( relationId );
			if ( relationId == aRelationId )
				{
				return ETrue;
				}
			}
		}

	return EFalse;
	}

TBool CMdSNotifyComparator::MatchRelationItemsL(
		    CMdCSerializationBuffer& aSerializedCondition,
		    CMdCSerializationBuffer& aSerializedItems,
		    RArray<TItemId>& aMatchingItemIdArray)
    {
    aSerializedItems.PositionL( KNoOffset );
    
    const TMdCItems& items = TMdCItems::GetFromBufferL( aSerializedItems );

    if( items.iRelations.iPtr.iCount == 0 )
    	{
    	return EFalse;
    	}

	for( TUint32 i = 0; i < items.iRelations.iPtr.iCount; i++ )
		{
		aSerializedItems.PositionL( items.iRelations.iPtr.iOffset + 
				+ i * sizeof(TMdCRelation) );
	    const TMdCRelation& relation = TMdCRelation::GetFromBufferL( aSerializedItems );

		if( aSerializedCondition.Size() > 0 )
			{
    		// move condition buffer's position to the begin of the buffer
    		aSerializedCondition.PositionL( KNoOffset );

    		if( MatchRelationItemL( aSerializedCondition, relation ) )
    			{
    			aMatchingItemIdArray.AppendL( relation.iId );
    			}
			}
		else
			{
			aMatchingItemIdArray.AppendL( relation.iId );
			}
		}

	if( aMatchingItemIdArray.Count() > 0 )
    	{
    	return ETrue;
    	}
    else
    	{
    	return EFalse;
    	}
    }

TBool CMdSNotifyComparator::MatchRelationItemL(CMdCSerializationBuffer& aSerializedCondition,
		   const TMdCRelation& aRelation)
	{
	// check if event is failed
	if( aRelation.iId == 0 )
		{
		return EFalse;
		}
	
	const TMdCRelationCondition& relationCondition = 
			TMdCRelationCondition::GetFromBufferL( aSerializedCondition );

	// check if relation condition contains relation def ID comparsion
	if( relationCondition.iRelationDefId != KNoDefId &&
		BoolEqual( relationCondition.iRelationDefId == aRelation.iDefId, 
				relationCondition.iNegated ) )
		{
		return EFalse;
		}
	
	// check if relation condition contains relation ID comparsion
	if ( relationCondition.iRelationId != KNoId &&
	 	 BoolEqual( relationCondition.iRelationId == aRelation.iId, 
	 			relationCondition.iNegated ) )
		{
		return EFalse;
		}

	// check if relation condition contains relation IDs comparsion
	if ( relationCondition.iRelationIds.iPtr.iOffset != KNoOffset &&
			BoolEqual( MatchRelationIdsL( relationCondition, 
					aSerializedCondition, aRelation.iId ), 
					relationCondition.iNegated ) )
		{
		return EFalse;
		}

	// check relation condition contains left and/or right object condition comparisions
	if ( ( relationCondition.iLeftObjectCondition != KNoOffset || 
			relationCondition.iRightObjectCondition != KNoOffset ) && 
			ERelationConditionSideEither == relationCondition.iObjectSide )
		{
		TBool eitherMatches = EFalse;
		
		if ( relationCondition.iLeftObjectCondition != KNoOffset )
			{
			aSerializedCondition.PositionL( 
					relationCondition.iLeftObjectCondition );
	
			if( !BoolEqual( MatchObjectIdToObjectIdConditionsL(
					aSerializedCondition, aRelation.iLeftObjectId ), 
					relationCondition.iNegated ) )
				{
				eitherMatches = ETrue;
				}
			}
		
		if ( relationCondition.iRightObjectCondition != KNoOffset )
			{
			aSerializedCondition.PositionL( 
					relationCondition.iRightObjectCondition );

			if( !BoolEqual( MatchObjectIdToObjectIdConditionsL(
					aSerializedCondition, aRelation.iRightObjectId ), 
					relationCondition.iNegated ) )
				{
				eitherMatches = ETrue;
				}
			}

		// left and right condition didn't match
		if( !eitherMatches )
			{
			return EFalse;
			}
		}

	return ETrue;
	}