phonebookengines_old/contactsmodel/cntmodel/src/CCntNotificationMonitor.cpp
changeset 40 b46a585f6909
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines_old/contactsmodel/cntmodel/src/CCntNotificationMonitor.cpp	Fri Jun 11 13:29:23 2010 +0300
@@ -0,0 +1,216 @@
+// Copyright (c) 2005-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:
+//
+
+/**
+ @file
+ @internalComponent
+ @released
+*/
+
+
+#include "ccontactprivate.h"
+#include "CCntNotificationMonitor.h"
+#include "rcntmodel.h"
+
+
+extern void DebugLogNotification(const TDesC& aMethod, const TContactDbObserverEvent &aEvent);
+
+
+CCntNotificationMonitor::CCntNotificationMonitor(RCntModel& aSession) 
+	: CActive(EPriorityStandard), iSession(aSession)
+	{}
+
+
+CCntNotificationMonitor::~CCntNotificationMonitor()
+	{
+	Cancel();
+	}
+
+
+void CCntNotificationMonitor::DoCancel() 
+	{
+	// TRequestStatus* status = &iStatus;
+	// User::RequestComplete(status, KErrNone);
+	}	
+
+
+/**
+This method is called each time the request for an event from the Server is
+completed.
+*/
+void CCntDbNotifyMonitor::RunL()
+	{
+	if ( iStatus == KErrDied || iStatus == KErrServerTerminated )
+		{
+		// We have lost our connection to the Server.  Attempt to restart it,
+		// reconnect the session and open the Contacts database.
+		iSession.HandlePrematureServerTerminationL();
+		// Request another event.
+		Start();
+		return;
+		}
+	
+	
+
+	
+	TInt count = iObserverArray.Count();
+	TContactDbObserverEvent& event = iEventMsg();
+	
+#if defined(__VERBOSE_DEBUG__)	
+	DebugLogNotification(_L("[CNTMODEL] CCntDbNotifyMonitor::RunL"), event);	
+#endif
+
+	// Notify all registered observers of the event.
+	for (TInt i = 0 ; i < count ; ++i)
+		{
+		iCurrentProcessedObserver = i;
+		// Ignore any leave so we can notify all registered observers.
+		TRAP_IGNORE(iObserverArray[i]->HandleDatabaseEventL(event));
+		// The call to HandleDatabaseEventL() above may remove or/add observer/observers
+		// so get the count again to cover this scenario. Also we have to update current
+		// loop counter.
+		i = iCurrentProcessedObserver;
+		count = iObserverArray.Count();
+		}
+	
+	// Request another event.
+	Start();
+	}
+
+	
+/**
+First phase constructor.
+*/
+CCntDbNotifyMonitor::CCntDbNotifyMonitor(RCntModel& aSession) 
+	: CCntNotificationMonitor(aSession), iCurrentProcessedObserver(KErrNotFound)
+	{}
+
+	
+/**
+Second phase constructor.
+
+@param aSession Client-side session handle for Contacts Model Server.
+*/
+CCntDbNotifyMonitor* CCntDbNotifyMonitor::NewL(RCntModel& aSession)
+	{
+	CCntDbNotifyMonitor* self = new (ELeave) CCntDbNotifyMonitor(aSession);
+	CActiveScheduler::Add(self);
+	return(self);
+	}
+
+
+CCntDbNotifyMonitor::~CCntDbNotifyMonitor()
+	{
+	iObserverArray.Close();
+	}
+
+	
+/**
+This method is called to request a Contacts database event from the Server.
+The RunL() method will be called when an event is available (i.e. when the
+Server completes the request.
+*/
+void CCntDbNotifyMonitor::Start()
+	{
+	// Check if a request for a Contacts database event from the Server has
+	// already been issued.
+	if (IsActive())
+		{
+		return;
+		}
+	iStatus=KRequestPending;
+	iSession.StartNotificationTransfer(iStatus, iEventMsg);	
+	SetActive();
+	}
+
+
+/**
+Add a Contacts database event observer.
+
+@param aObserver The Contacts database event observer to add.
+*/
+void CCntDbNotifyMonitor::AddObserverL(MContactDbObserver& aObserver)
+	{
+	// Observers can be added from HandleDatabaseEventL() called from CCntDbNotifyMonitor::RunL()
+	// To avoid overcomplicated algorithms for concurent access to handlers array, new observer will
+	// be added always at the end of array. Whilst duplications are not allowed, a search is 
+	// needed to check if observer is already added to observers array
+	
+	const TInt index = iObserverArray.Find(&aObserver);
+	if( index != KErrNotFound )
+		{
+		User::Leave( KErrAlreadyExists );
+		}
+	
+	User::LeaveIfError( iObserverArray.Append(&aObserver) );
+	
+	// At least one observer now added so start request for Contacts database
+	// event from the Server (if it hasn't already been started i.e. if the AO
+	// is not already active).
+	Start();
+	}
+
+
+/**
+Remove a Contacts database event observer.
+
+@param aObserver The Contacts database event observer to remove.
+*/
+void CCntDbNotifyMonitor::RemoveObserver(const MContactDbObserver& aObserver)
+	{
+	TInt index = iObserverArray.Find(&aObserver);
+	if (index != KErrNotFound)
+		{
+		iObserverArray.Remove(index);
+		
+		// Observers can be removed from HandleDatabaseEventL() called from CCntDbNotifyMonitor::RunL()
+		// In order to notify correctly remaining observers, we need to update current processed observer.
+		if( index <= iCurrentProcessedObserver )
+			{
+			--iCurrentProcessedObserver;
+			}
+			
+		}
+	// If there are no more observers then cancel the event request in the
+	// Server.
+	if (iObserverArray.Count() == 0)
+		{
+		iSession.EndNotificationTransfer();
+		}
+	}
+	
+
+/**
+Get the number of registered observers.
+
+@return The number of registered observers.
+*/
+TInt CCntDbNotifyMonitor::NumberOfListeners() const
+	{
+	return iObserverArray.Count();
+	}
+
+
+TInt CCntDbNotifyMonitor::RunError(TInt /*aError*/)
+	{
+#if defined(__VERBOSE_DEBUG__)	
+	TContactDbObserverEvent& event = iEventMsg();
+	DebugLogNotification(_L("[CNTMODEL] CCntDbNotifyMonitor::RunError"), event);		
+#endif
+
+	Start();
+		
+	return KErrNone;
+	}