pimprotocols/pbap/server/pbappbhandlecache.cpp
changeset 0 e686773b3f54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pimprotocols/pbap/server/pbappbhandlecache.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,280 @@
+// Copyright (c) 2006-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:
+//
+
+
+#include <cntdb.h>
+#include "pbapserver.h"
+#include "pbappbhandlecache.h"
+#include "btaccesshostlog.h"
+
+
+/*static*/ CPbapPbHandleCache* CPbapPbHandleCache::NewL(CContactDatabase& aDatabase, MPbHandleCacheObserver& aObserver)
+	{
+	LOG_STATIC_FUNC
+	CPbapPbHandleCache* self=new(ELeave) CPbapPbHandleCache(aDatabase, aObserver);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+
+CPbapPbHandleCache::CPbapPbHandleCache(CContactDatabase& aDatabase, MPbHandleCacheObserver& aObserver)
+	: iDatabase(aDatabase), iObserver(aObserver)
+	{
+	LOG_FUNC
+	}
+
+
+CPbapPbHandleCache::~CPbapPbHandleCache()
+	{
+	LOG_FUNC
+	iHandleList.Close();
+	delete iChangeNotifier;
+	}	
+
+
+void CPbapPbHandleCache::ConstructL()
+	{
+	LOG_FUNC
+	iChangeNotifier = CContactChangeNotifier::NewL(iDatabase, this);
+	CreateHandleListL();
+	}
+
+	
+TInt CPbapPbHandleCache::HandleAtL(TUint aIndex) const
+	{
+	LOG_FUNC
+	if(aIndex >= Count())
+		{
+		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicIndexOutOfBoundry));
+		User::Leave(KErrOverflow);
+		}
+	return iHandleList[aIndex].iHandle;
+	}
+	
+TContactItemId CPbapPbHandleCache::ContactIdAtL(TUint aIndex) const
+	{
+	LOG_FUNC
+	if(aIndex >= Count())
+		{
+		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicIndexOutOfBoundry));
+		User::Leave(KErrOverflow);
+		}
+	return iHandleList[aIndex].iContactId;
+	}
+
+
+TInt CPbapPbHandleCache::FindHandle(TInt aHandle) const
+	{
+	LOG_FUNC
+	// the array is ordered on handle so can use fast binary search
+	TPbHandleAndId item(aHandle, KNullContactId);
+	return iHandleList.FindInOrder(item, TLinearOrder<TPbHandleAndId>(CompareHandles));
+	}
+
+
+TInt CPbapPbHandleCache::FindContactId(TContactItemId aContactId) const
+	{
+	LOG_FUNC
+	// slow sequential search of array required for contact ids
+	TPbHandleAndId item(KErrNotFound, aContactId);
+	return iHandleList.Find(item, TIdentityRelation<TPbHandleAndId>(MatchContactIds));
+	}
+
+
+/*static*/
+TInt CPbapPbHandleCache::CompareHandles(const TPbHandleAndId& aFirst, const TPbHandleAndId& aSecond)
+	{
+	LOG_STATIC_FUNC
+	return (aFirst.iHandle - aSecond.iHandle);
+	}
+
+/*static*/	
+TBool CPbapPbHandleCache::MatchContactIds(const TPbHandleAndId& aFirst, const TPbHandleAndId& aSecond)
+	{
+	LOG_STATIC_FUNC
+	return (aFirst.iContactId == aSecond.iContactId);
+	}
+
+void CPbapPbHandleCache::CreateHandleListL()
+	{
+	LOG_FUNC
+	
+	iHandleList.Reset();
+	
+	// add own card handle item
+	TContactItemId ownCardId = iDatabase.OwnCardId();
+	TPbHandleAndId ownCardItem(KOwnCardHandle, ownCardId);
+	iHandleList.AppendL(ownCardItem);
+
+	// only include contact cards and the own card when building list
+	iDatabase.SetDbViewContactType(KUidContactCard);
+
+	// iterate through database building sorted list of handles
+	// (there should be a faster way of getting all the ids in the database,
+	// calling CContactDatabase::SortedItemsL() without a sort order used to
+	// be the quickest method but that has been deprecated)
+	TContactIter iter(iDatabase);
+	TContactItemId contactId = iter.FirstL();
+	TInt handle = 1;
+	while (contactId != KNullContactId)
+		{
+		if (contactId != ownCardId)
+			{
+			TPbHandleAndId item(handle, contactId); 
+			iHandleList.AppendL(item);
+			++handle; // increment handle
+			}
+		contactId = iter.NextL();
+		}
+	}
+
+	
+void CPbapPbHandleCache::HandleDatabaseEventL(TContactDbObserverEvent aEvent)
+	{
+	LOG_FUNC
+	switch(aEvent.iType)
+		{
+		case EContactDbObserverEventContactChanged:
+			{
+			// notify observer that a contact in the cache has changed
+			iObserver.HandleCacheChanged();
+			}
+			break;
+		case EContactDbObserverEventContactAdded:
+			{
+			// add contact id to cache (ignoring insert errors) and notify observer
+			HandleContactAddedL(aEvent.iContactId);
+			iObserver.HandleCacheChanged();
+			}
+			break;
+		case EContactDbObserverEventContactDeleted:
+			{	
+			// remove contact id from cache and notify observer 
+			HandleContactDeleted(aEvent.iContactId);
+			iObserver.HandleCacheChanged();
+			}
+			break;
+		case EContactDbObserverEventOwnCardChanged:
+			{
+			// the own card has been modified or another contact
+			// has been assigned as the own card
+			HandleOwnCardChangedL();
+			iObserver.HandleCacheChanged();			
+			}
+			break;
+		case EContactDbObserverEventOwnCardDeleted:
+			{	
+			// reset own card id back to KNullContactId
+			HandleOwnCardDeleted();
+			iObserver.HandleCacheChanged();
+			}
+			break;
+		case EContactDbObserverEventUnknownChanges:
+			{
+			// the database has changed but we do not know which
+			// contacts were affected, only choice is to rebuild handles cache  
+			#ifdef _DEBUG
+				TRAPD(error, CreateHandleListL());
+				if(error != KErrNone)
+					{
+					__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicUnexpectedError));
+					User::Leave(error);
+					}
+			#else
+				TRAP_IGNORE(CreateHandleListL());
+			#endif // _DEBUG
+			iObserver.HandleCacheChanged();
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+
+void CPbapPbHandleCache::HandleContactAddedL(TContactItemId aContactId)
+	{
+	LOG_FUNC
+	TPbHandleAndId item(NextAvailableHandleL(), aContactId);
+	iHandleList.AppendL(item);
+	}
+
+	
+void CPbapPbHandleCache::HandleContactDeleted(TContactItemId aContactId)
+	{
+	LOG_FUNC
+	TInt index= FindContactId(aContactId);
+	if (index != KErrNotFound)
+		{
+		iHandleList.Remove(index);
+		}
+	}
+
+
+void CPbapPbHandleCache::HandleOwnCardChangedL()
+	{
+	LOG_FUNC
+	TContactItemId ownCardId=iDatabase.OwnCardId();
+	TInt ownCardItemIndex = FindHandle(KOwnCardHandle); // always present
+	if(ownCardItemIndex == KErrNotFound)
+		{
+		__ASSERT_DEBUG(EFalse, Panic(EPbapServerPanicOwnCardNotFound));
+		User::Leave(KErrNotFound);
+		}
+	TContactItemId currentOwnCardId = ContactIdAtL(ownCardItemIndex);
+	if (ownCardId != currentOwnCardId)
+		{
+		if (currentOwnCardId != KNullContactId)
+			{	
+			// current own card now just another contact so assign to a new handle
+			TPbHandleAndId item(NextAvailableHandleL(), currentOwnCardId);
+			iHandleList.Append(item); // ignore the append error
+			}
+
+		// the new own card may already exist in the handle list, if so 
+		// remove it
+		if (ownCardId != KNullContactId)
+			{
+			TInt index = FindContactId(ownCardId);
+			if (index != KErrNotFound)
+				{
+				iHandleList.Remove(index);
+				}
+			}
+					
+		// replace contact id associated with own card handle
+		ownCardItemIndex = FindHandle(KOwnCardHandle);
+		iHandleList[ownCardItemIndex].iContactId = ownCardId;
+		}			
+	}
+	
+
+void CPbapPbHandleCache::HandleOwnCardDeleted()
+	{
+	LOG_FUNC
+	// reset own card id to null id
+	TInt ownCardItemIndex = FindHandle(KOwnCardHandle);
+	iHandleList[ownCardItemIndex].iContactId = KNullContactId;	
+	}
+	
+	
+TInt CPbapPbHandleCache::NextAvailableHandleL() const
+	{
+	LOG_FUNC
+	TInt lastHandle = HandleAtL(iHandleList.Count()-1);
+	return (lastHandle + 1); // just increment handle
+	}