--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/metadataengine/server/src/mdsnotifier.cpp Mon Jan 18 20:34:07 2010 +0200
@@ -0,0 +1,1021 @@
+/*
+* 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: Notifier engine / server side*
+*/
+
+#include "mdsnotifier.h"
+
+#include "mdcresult.h"
+#include "mdcitem.h"
+#include "mdsserversession.h"
+#include "mdsnotifycomparator.h"
+#include "mdslogger.h"
+#include "mdcserializationbuffer.h"
+#include "mdccommon.pan"
+
+__USES_LOGGER
+
+// ------------------------------------------------
+// NewL
+// ------------------------------------------------
+//
+CMdSNotifier* CMdSNotifier::NewL()
+ {
+ CMdSNotifier* that = CMdSNotifier::NewLC();
+ CleanupStack::Pop( that );
+ return that;
+ }
+
+
+// ------------------------------------------------
+// NewLC
+// ------------------------------------------------
+//
+CMdSNotifier* CMdSNotifier::NewLC()
+ {
+ CMdSNotifier* that = new(ELeave) CMdSNotifier();
+ CleanupStack::PushL( that );
+ that->ConstructL();
+ return that;
+ }
+
+
+// ------------------------------------------------
+// Constructor
+// ------------------------------------------------
+//
+CMdSNotifier::CMdSNotifier()
+ {
+
+ }
+
+// ------------------------------------------------
+// ConstructL
+// ------------------------------------------------
+//
+void CMdSNotifier::ConstructL()
+ {
+ iComparator = CMdSNotifyComparator::NewL();
+ }
+
+// ------------------------------------------------
+// Destructor
+// ------------------------------------------------
+//
+CMdSNotifier::~CMdSNotifier()
+ {
+ delete iComparator;
+ iEntries.Close();
+ }
+
+// ------------------------------------------------
+// Constructor
+// ------------------------------------------------
+//
+CMdSNotifier::TEntry::TEntry( TInt aId,
+ TConditionType aType,
+ CMdCSerializationBuffer* aSerializedBuffer,
+ TDefId aNamespaceDefId,
+ CMdSServerSession& aSession,
+ TBool aConfidential)
+ : iId( aId )
+ , iType( aType )
+ , iNamespaceDefId(aNamespaceDefId)
+ , iSerializedCondition( aSerializedBuffer )
+ , iSession( aSession )
+ , iConfidential(aConfidential)
+ {
+ iDataBuffer = NULL;
+ iRemoteSizeMsgSlot = KErrNotFound;
+ }
+
+// ------------------------------------------------
+// TriggerL completes the client message and sends the data size
+// ------------------------------------------------
+//
+void CMdSNotifier::TEntry::TriggerL(
+ TUint32 aCompleteCode,
+ const RArray<TItemId>& aIdArray )
+ {
+ TInt remoteSizeMsgSlot = iRemoteSizeMsgSlot;
+ iRemoteSizeMsgSlot = KErrNotFound;
+
+ __ASSERT_DEBUG( !iDataBuffer, MMdCCommon::Panic( KErrCorrupt ) );
+
+ if(aIdArray.Count())
+ {
+ iDataBuffer = CopyToBufferL( aIdArray );
+ iSession.SizeToRemoteL( iMessage, remoteSizeMsgSlot, iDataBuffer->Size());
+ }
+ else
+ {
+ iSession.SizeToRemoteL( iMessage, remoteSizeMsgSlot, 0);
+ }
+
+ __LOG2( ELogServer, "<- Notify trigger %d (%d)", iId, aCompleteCode );
+ iMessage.Complete( aCompleteCode );
+ }
+
+// ------------------------------------------------
+// TriggerRelationItemsL completes the client
+// message and sends the data size
+// ------------------------------------------------
+//
+void CMdSNotifier::TEntry::TriggerRelationItemsL(
+ TUint32 aCompleteCode,
+ CMdCSerializationBuffer& aBuffer,
+ const RArray<TItemId>& aRelationIdArray)
+ {
+ TInt remoteSizeMsgSlot = iRemoteSizeMsgSlot;
+ iRemoteSizeMsgSlot = KErrNotFound;
+
+ __ASSERT_DEBUG( !iDataBuffer, MMdCCommon::Panic( KErrCorrupt ) );
+
+ if(aRelationIdArray.Count())
+ {
+ iDataBuffer = CopyItemsToBufferL( aBuffer, aRelationIdArray );
+ iSession.SizeToRemoteL( iMessage, remoteSizeMsgSlot, iDataBuffer->Size());
+ }
+ else
+ {
+ iSession.SizeToRemoteL( iMessage, remoteSizeMsgSlot, 0);
+ }
+
+ __LOG2( ELogServer, "<- Notify trigger %d (%d)", iId, aCompleteCode );
+ iMessage.Complete( aCompleteCode );
+ }
+
+// ------------------------------------------------
+// TriggerSchemaL sends a schema notification
+// ------------------------------------------------
+//
+void CMdSNotifier::TEntry::TriggerSchema()
+ {
+ iRemoteSizeMsgSlot = KErrNotFound;
+ iMessage.Complete( ESchemaModify );
+ }
+
+// ------------------------------------------------
+// TriggerError send a error message to the client
+// ------------------------------------------------
+//
+void CMdSNotifier::TEntry::TriggerError( TInt aErrorCode )
+ {
+ iRemoteSizeMsgSlot = KErrNotFound;
+ delete iDataBuffer;
+ iDataBuffer = NULL;
+ __LOG2( ELogServer, "<- Notify trigger %d (%d)", iId, aErrorCode );
+
+ if( !iMessage.IsNull() )
+ {
+ iMessage.Complete( aErrorCode );
+ }
+ }
+
+// ------------------------------------------------
+// CopyToBufferL copies id to buffer
+// ------------------------------------------------
+//
+CMdCSerializationBuffer* CMdSNotifier::TEntry::CopyToBufferL(const RArray<TItemId>& aIdArray)
+ {
+ // IDs are always stored in object ID,
+ // even if those are actually relation or event IDs
+
+ const TUint32 count = aIdArray.Count();
+
+ CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC(
+ sizeof( TMdCItemIds )
+ + count * CMdCSerializationBuffer::KRequiredSizeForTItemId );
+
+ TMdCItemIds itemIds;
+ itemIds.iNamespaceDefId = NamespaceDefId();
+ itemIds.iObjectIds.iPtr.iCount = count;
+ itemIds.iObjectIds.iPtr.iOffset = sizeof(TMdCItemIds);
+ itemIds.SerializeL( *buffer );
+
+ for( TInt i = 0; i < count; ++i )
+ {
+ buffer->InsertL( aIdArray[i] );
+ }
+
+ CleanupStack::Pop( buffer );
+ return buffer;
+ }
+
+// ------------------------------------------------
+// CopyItemsToBufferL copies relation items to buffer
+// ------------------------------------------------
+//
+CMdCSerializationBuffer* CMdSNotifier::TEntry::CopyItemsToBufferL(
+ CMdCSerializationBuffer& aRelationItemsBuffer,
+ const RArray<TItemId>& aIdArray)
+ {
+ const TUint32 count = aIdArray.Count();
+ aRelationItemsBuffer.PositionL( KNoOffset );
+ const TMdCItems& items = TMdCItems::GetFromBufferL( aRelationItemsBuffer );
+
+ CMdCSerializationBuffer* buffer = NULL;
+ if ( items.iRelations.iPtr.iCount == count )
+ {
+ buffer = CMdCSerializationBuffer::NewLC( aRelationItemsBuffer );
+ }
+ else
+ {
+ buffer = CMdCSerializationBuffer::NewLC( sizeof(TMdCItems)
+ + count * sizeof(TMdCRelation) );
+
+ TMdCItems returnItems;
+ returnItems.iNamespaceDefId = items.iNamespaceDefId;
+ returnItems.iRelations.iPtr.iCount = count;
+ returnItems.iRelations.iPtr.iOffset = sizeof(TMdCItems);
+ buffer->PositionL( sizeof(TMdCItems) );
+
+ for( TInt i = 0; i < items.iRelations.iPtr.iCount; ++i )
+ {
+ TMdCRelation relation;
+ relation.DeserializeL( aRelationItemsBuffer );
+
+ if ( aIdArray.Find( relation.iId ) >= 0 )
+ {
+ relation.SerializeL( *buffer );
+ }
+ }
+ buffer->PositionL( KNoOffset );
+ returnItems.SerializeL( *buffer );
+ }
+
+ CleanupStack::Pop( buffer );
+ return buffer;
+ }
+
+// ------------------------------------------------
+// CacheL caches the notification
+// ------------------------------------------------
+//
+void CMdSNotifier::TEntry::CacheL(TUint32 aCompleteCode, const RArray<TItemId>& aIdArray )
+ {
+ if ( aIdArray.Count() <= 0 )
+ {
+ return;
+ }
+
+ CMdCSerializationBuffer* data = CopyToBufferL( aIdArray );
+ iSession.CacheNotificationL( iId, aCompleteCode, data );
+ }
+
+// ------------------------------------------------
+// CacheRelationItemsL caches the notification
+// ------------------------------------------------
+//
+void CMdSNotifier::TEntry::CacheRelationItemsL(TUint32 aCompleteCode,
+ CMdCSerializationBuffer& aBuffer,
+ const RArray<TItemId>& aRelationIdArray )
+ {
+ CMdCSerializationBuffer* data = CopyItemsToBufferL( aBuffer,
+ aRelationIdArray );
+ iSession.CacheNotificationL(iId, aCompleteCode, data);
+ }
+
+// ------------------------------------------------
+// CacheL for schema mods
+// ------------------------------------------------
+//
+void CMdSNotifier::TEntry::CacheL(TUint32 aCompleteCode)
+ {
+ iSession.CacheNotificationL(iId, aCompleteCode, NULL);
+ }
+
+// ------------------------------------------------
+// TriggerCachedL triggers a previously cached notification
+// ------------------------------------------------
+//
+void CMdSNotifier::TEntry::TriggerCachedL(TUint32 aCompleteCode,
+ CMdCSerializationBuffer* aData)
+ {
+ TInt remoteSizeMsgSlot = iRemoteSizeMsgSlot;
+ iRemoteSizeMsgSlot = KErrNotFound;
+
+ __ASSERT_DEBUG( !iDataBuffer, MMdCCommon::Panic( KErrCorrupt ) );
+
+ if( aData )
+ {
+ iSession.SizeToRemoteL( iMessage, remoteSizeMsgSlot, aData->Size());
+ }
+
+ iDataBuffer = aData;
+
+ __LOG2( ELogServer, "<- Notify trigger %d (%d)", iId, aCompleteCode );
+ iMessage.Complete( aCompleteCode );
+ }
+
+// ------------------------------------------------
+// SetupForCallback
+// ------------------------------------------------
+//
+void CMdSNotifier::TEntry::SetupForCallback(
+ RMessage2 aMessage, TInt aRemoteSizeMsgSlot )
+ {
+ __ASSERT_DEBUG( !IsPending(), MMdCCommon::Panic( KErrCorrupt ) );
+ iMessage = aMessage;
+ iRemoteSizeMsgSlot = aRemoteSizeMsgSlot;
+ }
+
+// ------------------------------------------------
+// GetDataBuffer
+// ------------------------------------------------
+//
+CMdCSerializationBuffer* CMdSNotifier::TEntry::GetDataBuffer()
+ {
+ CMdCSerializationBuffer* data = iDataBuffer;
+ iDataBuffer = NULL;
+ return data;
+ }
+
+// ------------------------------------------------
+// CreateEntry creates a new notifier entry
+// ------------------------------------------------
+//
+CMdSNotifier::TEntry& CMdSNotifier::CreateEntryL( TInt aId,
+ TConditionType aType, CMdCSerializationBuffer* aSerializedBuffer,
+ TDefId aNamespaceDefId, CMdSServerSession& aSession, TBool aConfidential )
+ {
+
+ User::LeaveIfError( iEntries.Append(
+ TEntry( aId, aType, aSerializedBuffer, aNamespaceDefId, aSession, aConfidential ) ) );
+ return iEntries[ iEntries.Count() - 1 ];
+ }
+
+// ------------------------------------------------
+// FindEntry
+// ------------------------------------------------
+//
+CMdSNotifier::TEntry& CMdSNotifier::FindEntryL( TInt aId )
+ {
+ CMdSNotifier::TEntry* entry = NULL;
+
+ const TInt count = iEntries.Count();
+
+ for ( TInt i = 0; i < count; ++i )
+ {
+ if ( iEntries[i].iId == aId )
+ {
+ entry = &iEntries[i];
+ break;
+ }
+ }
+
+ if( !entry )
+ {
+ User::Leave( KErrNotFound );
+ }
+
+ return *entry;
+ }
+
+// ------------------------------------------------
+// RemoveEntryL
+// ------------------------------------------------
+//
+void CMdSNotifier::RemoveEntryL( TInt aId )
+ {
+ const TInt count = iEntries.Count();
+
+ for ( TInt i = 0; i < count; ++i )
+ {
+ TEntry& e = iEntries[i];
+ if ( e.iId == aId )
+ {
+ if ( e.IsPending() )
+ {
+ e.TriggerError( KErrCancel );
+ }
+
+ if ( e.iSerializedCondition )
+ {
+ delete e.iSerializedCondition;
+ e.iSerializedCondition = NULL;
+ }
+ if ( e.iDataBuffer )
+ {
+ delete e.iDataBuffer;
+ e.iDataBuffer = NULL;
+ }
+ iEntries.Remove( i );
+ return;
+ }
+ }
+ User::Leave( KErrNotFound );
+ }
+
+// ------------------------------------------------
+// RemoveEntriesBySession
+// ------------------------------------------------
+//
+void CMdSNotifier::RemoveEntriesBySession(
+ const CMdSServerSession& aSession )
+ {
+ const TInt count = iEntries.Count();
+
+ for ( TInt i = count; --i >= 0; )
+ {
+ TEntry& e = iEntries[i];
+ if ( &e.iSession == &aSession ) // pointer comparision
+ {
+ if ( e.IsPending() )
+ {
+ e.TriggerError( KErrCancel );
+ }
+
+ delete e.iSerializedCondition;
+ delete e.iDataBuffer;
+ iEntries.Remove( i );
+ }
+ }
+ }
+
+// ------------------------------------------------
+// NotifyAdded
+// ------------------------------------------------
+//
+void CMdSNotifier::NotifyAddedL(CMdCSerializationBuffer& aSerializedItems,
+ CMdCSerializationBuffer& aSerializedItemIds)
+ {
+ const TInt count = iEntries.Count();
+
+ for( TInt i = 0; i < count; ++i )
+ {
+ TEntry& e = iEntries[i];
+
+ if ( ! (e.iType & ( EObjectNotifyAdd | ERelationNotifyAdd | EEventNotifyAdd ) ) )
+ {
+ continue;
+ }
+
+ RArray<TItemId> matchingItemIdArray;
+ CleanupClosePushL( matchingItemIdArray );
+
+ aSerializedItems.PositionL( KNoOffset );
+ aSerializedItemIds.PositionL( KNoOffset );
+
+ TBool someMatches = iComparator->MatchL( e.NamespaceDefId(), e.iType, e.Condition(),
+ aSerializedItems, aSerializedItemIds,
+ matchingItemIdArray,
+ e.AllowConfidential() );
+
+ if( someMatches ) // check if there is some matches
+ {
+ if( e.IsPending() )
+ {
+ // match found. trigger notifier entry !
+ TRAPD( err, e.TriggerL( EObjectNotifyAdd | ERelationNotifyAdd | EEventNotifyAdd,
+ matchingItemIdArray ) );
+ if( err != KErrNone )
+ {
+ e.TriggerError( err );
+ }
+ }
+ else
+ {
+ TRAP_IGNORE( e.CacheL( EObjectNotifyAdd | ERelationNotifyAdd | EEventNotifyAdd,
+ matchingItemIdArray ) );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &matchingItemIdArray );
+ }
+ }
+
+// ------------------------------------------------
+// NotifyRemoved
+// ------------------------------------------------
+//
+void CMdSNotifier::NotifyRemovedL(CMdCSerializationBuffer& aSerializedItemIds,
+ TBool aItemIsConfidential)
+ {
+ aSerializedItemIds.PositionL( KNoOffset );
+
+ const TMdCItemIds& itemIds = TMdCItemIds::GetFromBufferL( aSerializedItemIds );
+
+ RArray<TItemId> objectIdArray;
+ CleanupClosePushL( objectIdArray );
+ RArray<TItemId> eventIdArray;
+ CleanupClosePushL( eventIdArray );
+ RArray<TItemId> relationIdArray;
+ CleanupClosePushL( relationIdArray );
+
+ //get removed item IDs
+ if( itemIds.iObjectIds.iPtr.iCount > 0 )
+ {
+ aSerializedItemIds.PositionL( itemIds.iObjectIds.iPtr.iOffset );
+
+ objectIdArray.ReserveL( itemIds.iObjectIds.iPtr.iCount );
+ for( TUint32 i = 0; i < itemIds.iObjectIds.iPtr.iCount; i++ )
+ {
+ TItemId objectId;
+ aSerializedItemIds.ReceiveL( objectId );
+ if ( objectId != KNoId )
+ {
+ objectIdArray.Append( objectId );
+ }
+ }
+ }
+ if( itemIds.iEventIds.iPtr.iCount > 0 )
+ {
+ aSerializedItemIds.PositionL( itemIds.iEventIds.iPtr.iOffset );
+
+ eventIdArray.ReserveL( itemIds.iEventIds.iPtr.iCount );
+ for( TUint32 i = 0; i < itemIds.iEventIds.iPtr.iCount; i++ )
+ {
+ TItemId eventId;
+ aSerializedItemIds.ReceiveL( eventId );
+ if ( eventId != KNoId )
+ {
+ eventIdArray.Append( eventId );
+ }
+ }
+ }
+ if( itemIds.iRelationIds.iPtr.iCount > 0 )
+ {
+ aSerializedItemIds.PositionL( itemIds.iRelationIds.iPtr.iOffset );
+
+ relationIdArray.ReserveL( itemIds.iRelationIds.iPtr.iCount );
+ for( TUint32 i = 0; i < itemIds.iRelationIds.iPtr.iCount; i++ )
+ {
+ TItemId relationId;
+ aSerializedItemIds.ReceiveL( relationId );
+ if ( relationId != KNoId )
+ {
+ relationIdArray.Append( relationId );
+ }
+ }
+ }
+
+ if( objectIdArray.Count() != 0
+ || eventIdArray.Count() != 0
+ || relationIdArray.Count() != 0 )
+ {
+ const TInt entriesCount = iEntries.Count();
+ for( TInt i=0; i < entriesCount; ++i )
+ {
+ TEntry& e = iEntries[i];
+
+ // if namespace definition IDs don't match skip listener entry
+ if( e.NamespaceDefId() != itemIds.iNamespaceDefId )
+ {
+ continue;
+ }
+
+ if(aItemIsConfidential && !e.AllowConfidential())
+ {
+ continue;
+ }
+
+ if( e.iType & EObjectNotifyRemove && objectIdArray.Count() > 0 )
+ {
+ // collect matching object IDs
+ RArray<TItemId> matchingObjectIdArray;
+ CleanupClosePushL( matchingObjectIdArray );
+
+ TBool allMatches = iComparator->MatchObjectIdsL( e.Condition(),
+ objectIdArray, matchingObjectIdArray );
+
+ // check is there any matches
+ if( allMatches || matchingObjectIdArray.Count() > 0 )
+ {
+ if(e.IsPending())
+ {
+ // Match found. Trigger notifier entry.
+ TInt err;
+
+ if( allMatches )
+ {
+ // all matches so send whole object ID array
+ TRAP( err, e.TriggerL( EObjectNotifyRemove,
+ objectIdArray ) );
+ }
+ else
+ {
+ TRAP( err, e.TriggerL( EObjectNotifyRemove,
+ matchingObjectIdArray ) );
+ }
+
+ if( err != KErrNone )
+ {
+ e.TriggerError( err );
+ }
+ }
+ else
+ {
+ if( allMatches )
+ {
+ // all matches so send whole object ID array
+ TRAP_IGNORE( e.CacheL( EObjectNotifyRemove,
+ objectIdArray ) );
+ }
+ else
+ {
+ TRAP_IGNORE( e.CacheL( EObjectNotifyRemove,
+ matchingObjectIdArray ) );
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &matchingObjectIdArray );
+ }
+ else if( ( e.iType & EEventNotifyRemove )
+ && eventIdArray.Count() > 0 )
+ {
+ // event condition can't contain ID conditions,
+ // so get all IDs
+ if(e.IsPending())
+ {
+ // Match found. Trigger notifier entry.
+ TRAPD( err, e.TriggerL( EEventNotifyRemove,
+ eventIdArray ) );
+ if( err != KErrNone )
+ {
+ e.TriggerError( err );
+ }
+ }
+ else
+ {
+ TRAP_IGNORE( e.CacheL( EEventNotifyRemove,
+ eventIdArray ) );
+ }
+ }
+ else if( ( e.iType & ERelationNotifyRemove )
+ && relationIdArray.Count() > 0 )
+ {
+ // relation condition can't contain ID conditions,
+ // so get all IDs
+ if(e.IsPending())
+ {
+ // Match found. Trigger notifier entry.
+ TRAPD( err, e.TriggerL( ERelationNotifyRemove,
+ relationIdArray ) );
+ if( err != KErrNone )
+ {
+ e.TriggerError( err );
+ }
+ }
+ else
+ {
+ TRAP_IGNORE( e.CacheL( ERelationNotifyRemove,
+ relationIdArray ) );
+ }
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy( 3, &objectIdArray ); // relationIdArray, eventIdArray, objectIdArray
+ }
+
+// ------------------------------------------------
+// NotifyModified
+// ------------------------------------------------
+//
+void CMdSNotifier::NotifyModifiedL(CMdCSerializationBuffer& aSerializedItems,
+ CMdCSerializationBuffer& aSerializedItemIds)
+ {
+ const TInt count = iEntries.Count();
+
+ for( TInt i = 0; i < count; ++i )
+ {
+ TEntry& e = iEntries[i];
+
+ if ( ! (e.iType & ( EObjectNotifyModify | ERelationNotifyModify /*| ERelationItemNotifyModify*/ ) ) )
+ {
+ continue;
+ }
+
+ RArray<TItemId> matchingObjectIdArray;
+ CleanupClosePushL( matchingObjectIdArray );
+
+ aSerializedItems.PositionL( KNoOffset );
+ aSerializedItemIds.PositionL( KNoOffset );
+
+ TBool someMatches = iComparator->MatchL( e.NamespaceDefId(),
+ e.iType, e.Condition(), aSerializedItems, aSerializedItemIds,
+ matchingObjectIdArray, e.AllowConfidential() );
+
+ if( someMatches ) // check if there is some matches
+ {
+ if( e.IsPending() )
+ {
+ // match found. trigger notifier entry !
+ TRAPD( err, e.TriggerL( EObjectNotifyModify | ERelationNotifyModify /*| ERelationItemNotifyModify*/,
+ matchingObjectIdArray ) );
+ if( err != KErrNone )
+ {
+ e.TriggerError( err );
+ }
+ }
+ else
+ {
+ TRAP_IGNORE( e.CacheL( EObjectNotifyModify | ERelationNotifyModify /*| ERelationItemNotifyModify*/,
+ matchingObjectIdArray ) );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &matchingObjectIdArray );
+ }
+ }
+
+// ------------------------------------------------
+// NotifyModified
+// ------------------------------------------------
+//
+void CMdSNotifier::NotifyModifiedL(const RArray<TItemId>& aObjectIds)
+ {
+ if (aObjectIds.Count() == 0)
+ {
+ return;
+ }
+
+ const TInt count = iEntries.Count();
+
+ for( TInt i = 0; i < count; ++i )
+ {
+ TEntry& e = iEntries[i];
+
+ if( e.iType & EObjectNotifyModify )
+ {
+ // collect matching object IDs
+ RArray<TItemId> matchingObjectIdArray;
+ CleanupClosePushL( matchingObjectIdArray );
+
+ TBool allMatches = iComparator->MatchObjectIdsL( e.Condition(),
+ aObjectIds, matchingObjectIdArray );
+
+ // check is there any matches
+ if( allMatches || matchingObjectIdArray.Count() > 0 )
+ {
+ if(e.IsPending())
+ {
+ // Match found. Trigger notifier entry.
+ TInt err;
+
+ if( allMatches )
+ {
+ // all matches so send whole object ID array
+ TRAP( err, e.TriggerL( EObjectNotifyModify,
+ aObjectIds ) );
+ }
+ else
+ {
+ TRAP( err, e.TriggerL( EObjectNotifyModify,
+ matchingObjectIdArray ) );
+ }
+
+ if( err != KErrNone )
+ {
+ e.TriggerError( err );
+ }
+ }
+ else
+ {
+ if( allMatches )
+ {
+ // all matches so send whole object ID array
+ TRAP_IGNORE( e.CacheL( EObjectNotifyModify,
+ aObjectIds ) );
+ }
+ else
+ {
+ TRAP_IGNORE( e.CacheL( EObjectNotifyModify,
+ matchingObjectIdArray ) );
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &matchingObjectIdArray );
+ }
+ }
+ }
+
+// ------------------------------------------------
+// NotifyRemoved
+// ------------------------------------------------
+//
+void CMdSNotifier::NotifyRemovedL(const RArray<TItemId>& aItemIdArray)
+ {
+ for( TInt i=0; i<iEntries.Count(); ++i )
+ {
+ TEntry& e = iEntries[i];
+
+ if( e.iType & EObjectNotifyRemove )
+ {
+ if( e.IsPending() )
+ {
+ TRAPD( err, e.TriggerL( EObjectNotifyRemove, aItemIdArray ) );
+ if( err != KErrNone )
+ {
+ e.TriggerError( err );
+ }
+ }
+ else
+ {
+ TRAP_IGNORE( e.CacheL( EObjectNotifyRemove, aItemIdArray ) );
+ }
+ }
+ }
+ }
+
+// ------------------------------------------------
+// NotifyObjectPresent
+// ------------------------------------------------
+//
+void CMdSNotifier::NotifyObjectPresent(TBool aPresent, const RArray<TItemId>& aObjectIds)
+ {
+ if (aObjectIds.Count() == 0)
+ {
+ return;
+ }
+
+ const TInt count = iEntries.Count();
+
+ for( TInt i = 0; i < count; ++i )
+ {
+ TEntry& e = iEntries[i];
+
+ // No condition matching, object present changes
+ // are always notified to object present observers
+ if( e.iType & ( EObjectNotifyPresent | EObjectNotifyNotPresent ) )
+ {
+ const TMdSObserverNotificationType objectState =
+ aPresent ? EObjectNotifyPresent : EObjectNotifyNotPresent;
+
+ if( e.IsPending() )
+ {
+ // match found. trigger notifier entry !
+ TRAPD( err, e.TriggerL( objectState, aObjectIds ) );
+ if( err != KErrNone )
+ {
+ e.TriggerError( err );
+ }
+ }
+ else
+ {
+ TRAP_IGNORE( e.CacheL( objectState, aObjectIds ) );
+ }
+ }
+ }
+ }
+
+// ------------------------------------------------
+// NotifyRelationPresent
+// ------------------------------------------------
+//
+void CMdSNotifier::NotifyRelationPresent(TBool aPresent, const RArray<TItemId>& aRelationIds)
+ {
+ if (aRelationIds.Count() == 0)
+ {
+ return;
+ }
+
+ const TInt count = iEntries.Count();
+
+ for( TInt i = 0; i < count; ++i )
+ {
+ TEntry& e = iEntries[i];
+
+ // No condition matching, relation present changes
+ // are always notified to relation present observers
+ if( e.iType & ( ERelationNotifyPresent | ERelationNotifyNotPresent ) )
+ {
+ const TMdSObserverNotificationType relationState =
+ aPresent ? ERelationNotifyPresent : ERelationNotifyNotPresent;
+
+ if( e.IsPending() )
+ {
+ // match found. trigger notifier entry !
+ TRAPD( err, e.TriggerL( relationState, aRelationIds ) );
+ if( err != KErrNone )
+ {
+ e.TriggerError( err );
+ }
+ }
+ else
+ {
+ TRAP_IGNORE( e.CacheL( relationState, aRelationIds ) );
+ }
+ }
+ }
+ }
+
+
+// ------------------------------------------------
+// NotifySchemaAdded
+// ------------------------------------------------
+//
+void CMdSNotifier::NotifySchemaAddedL()
+ {
+ const TInt count = iEntries.Count();
+
+ for( TInt i = 0; i < count; ++i )
+ {
+ TEntry& e = iEntries[i];
+
+ // No condition matching, schema additions
+ // are always notified to schema observers
+ if( e.iType == ESchemaModify )
+ {
+ if( e.IsPending() )
+ {
+ // match found. trigger notifier entry
+ e.TriggerSchema();
+ }
+ else
+ {
+ TRAP_IGNORE( e.CacheL( ESchemaModify ) );
+ }
+ }
+ }
+ }
+
+
+// ------------------------------------------------
+// CheckForNotifier
+// ------------------------------------------------
+//
+TBool CMdSNotifier::CheckForNotifier( TUint32 aNotifyTypes )
+ {
+ const TInt count = iEntries.Count();
+
+ for( TInt i = 0; i < count; ++i )
+ {
+ if ( iEntries[i].iType & aNotifyTypes )
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+void CMdSNotifier::NotifyRemovedRelationItemsL(
+ CMdCSerializationBuffer& aBuffer )
+ {
+ aBuffer.PositionL( KNoOffset );
+
+ const TMdCItems& items = TMdCItems::GetFromBufferL( aBuffer );
+
+ if( items.iRelations.iPtr.iCount )
+ {
+ const TInt entriesCount = iEntries.Count();
+ for( TInt i = 0; i < entriesCount; ++i )
+ {
+ TEntry& e = iEntries[i];
+
+ // if namespace definition IDs don't match skip listener entry
+ if( e.NamespaceDefId() != items.iNamespaceDefId )
+ {
+ continue;
+ }
+
+ if( e.iType & ERelationItemNotifyRemove )
+ {
+ aBuffer.PositionL( items.iRelations.iPtr.iOffset );
+ // check relations condition
+ RArray<TItemId> matchedRelations;
+ CleanupClosePushL( matchedRelations );
+ TBool matches = iComparator->MatchRelationItemsL(
+ e.Condition(), aBuffer, matchedRelations );
+
+ if ( matches )
+ {
+ if(e.IsPending())
+ {
+ // Match found. Trigger notifier entry.
+ TRAPD( err, e.TriggerRelationItemsL(
+ ERelationItemNotifyRemove, aBuffer,
+ matchedRelations ) );
+ if( err != KErrNone )
+ {
+ e.TriggerError( err );
+ }
+ }
+ else
+ {
+ TRAP_IGNORE( e.CacheRelationItemsL(
+ ERelationItemNotifyRemove, aBuffer,
+ matchedRelations ) );
+ }
+ }
+ CleanupStack::PopAndDestroy( &matchedRelations );
+ }
+ }
+ }
+
+ }
+