diff -r 000000000000 -r e686773b3f54 pimprotocols/pbap/server/pbappbhandlecache.cpp --- /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 +#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(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(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 + }