diff -r 000000000000 -r 094583676ce7 PECengine/JanitorPlugin2/Src/CPEngContactMapper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PECengine/JanitorPlugin2/Src/CPEngContactMapper.cpp Thu Dec 17 08:41:52 2009 +0200 @@ -0,0 +1,506 @@ +/* +* Copyright (c) 2005 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: Container of one contact list item. It includes, wv ID, nick name, +* List of contact IDs, flag if there is need to notify about change of the +* Presence change of the wv ID, and flag if wv ID: was checked by Janitor +* +*/ + + + +// INCLUDE FILES +#include "CPEngContactMapper.h" + +#include +#include +#include + +#include "CPEngListObserver.h" +#include "CPEngContact.h" + +#include "CPEngNWSessionSlotNotifier2.h" +#include "CPEngNWSessionSlotEvent2.h" +#include "CPEngNWSessionSlotID2.h" + +// Debug prints +#include "PresenceDebugPrint.h" + + +// CONSTANTS +#define ORDER TLinearOrder (CPEngContact::Compare) + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::CPEngContactMapper +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CPEngContactMapper::CPEngContactMapper() + { + PENG_DP( D_PENG_LIT( "PEngJanitorPlugIn: CPEngContactMapper::CPEngContactMapper" ) ); + } + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CPEngContactMapper::ConstructL() + { + // create contact cache and register observer + iCntDatabase = CContactDatabase::OpenL(); + iCntNotifier = CContactChangeNotifier::NewL( *iCntDatabase, this ); + RebuildContactDbCacheL(); + + iSessionNotifier = CPEngNWSessionSlotNotifier2::NewL(); + User::LeaveIfError( iSessionNotifier->AddObserver( *this ) ); + User::LeaveIfError( iSessionNotifier->Start() ); + } + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CPEngContactMapper* CPEngContactMapper::NewL() + { + CPEngContactMapper* self = NewLC( ); + + CleanupStack::Pop(); // self + + return self; + } + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CPEngContactMapper* CPEngContactMapper::NewLC() + { + CPEngContactMapper* self = new( ELeave ) CPEngContactMapper(); + + CleanupStack::PushL( self ); + self->ConstructL( ); + + return self; + } + +// Destructor +CPEngContactMapper::~CPEngContactMapper() + { + iContacts.ResetAndDestroy(); + iListObservers.ResetAndDestroy(); + delete iSessionNotifier; + delete iCntNotifier; + delete iCntDatabase; + } + +// ============================================================================= +// ===============Function for MPEngContactMapper class ======================== +// ============================================================================= + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::MappWvIdL +// Map wv id to the contact db id +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CContactIdArray* CPEngContactMapper::MapWvIdToContactIdLC( + const TDesC& aWVId ) + { + CContactIdArray* contactIds = NULL; + TInt count ( iContacts.Count() ); + for ( TInt x( 0 ) ; x < count ; ++x ) + { + if ( iContacts[ x ]->ValidateWVId( aWVId ) ) + { + if ( !contactIds ) + { + contactIds = CContactIdArray::NewLC(); + } + contactIds->AddL( iContacts[ x ]->ContactId() ); + } + } + // even no contact id was created, push NULL to maintain LC continuity + if ( !contactIds ) + { + CleanupStack::PushL( contactIds ); + } + return contactIds; + } + +// ============================================================================= +// ===============Function for MContactDBObserver class ======================== +// ============================================================================= + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::HandleDatabaseEventL +// Handle Contact Database event +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngContactMapper::HandleDatabaseEventL( + TContactDbObserverEvent aEvent ) + { + switch ( aEvent.iType ) + { + case EContactDbObserverEventContactDeleted: + { + RemoveContactL( aEvent.iContactId ); + break; + } + case EContactDbObserverEventContactAdded: + { + AddContactL( aEvent.iContactId ); + break; + } + case EContactDbObserverEventContactChanged: + { + UpdateContactL( aEvent.iContactId ); + break; + } + case EContactDbObserverEventUnknownChanges: + { + // reload whole contact cache, since more changes has happened + HandleMultipleChangesL(); + } + default: + { + break; + } + } + } + + +// ============================================================================= +// ===============Function for MPEngNWSessionSlotObserver2 class =============== +// ============================================================================= + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::HandleNWSessionSlotChangeL +// NWSessionSlot change handler. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngContactMapper::HandleNWSessionSlotChangeL( + CPEngNWSessionSlotNotifier2& /*aNotifier*/, + CPEngNWSessionSlotEvent2& aEvent ) + { + TInt index( FindListObserver( aEvent.NWSessionSlotID() ) ); + if ( EPEngNWPresenceSessionOpen == aEvent.NWSessionSlotState() ) + { + // make sure we are observing such a session + if ( index != KErrNotFound ) + { + return; + } + CPEngListObserver* observer = CPEngListObserver::NewLC( + *this, + aEvent.NWSessionSlotID() ); + iListObservers.AppendL( observer ); + CleanupStack::Pop( observer ); // observer + } + else + { + // stop observing of such a session + if ( index != KErrNotFound ) + { + delete iListObservers[ index ]; + iListObservers.Remove( index ); + } + } + } + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::HandleNWSessionSlotError +// Notification failure handler. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngContactMapper::HandleNWSessionSlotError( + TInt /*aError*/, + CPEngNWSessionSlotNotifier2& /*aNotifier */ ) + { + // no error handling here + } + +// ============================================================================= +// =============== New Function of base class ================================= +// ============================================================================= + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::AddContactL +// Inserts new contact to the contact db cache +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngContactMapper::AddContactL( + TContactItemId& aContactId ) + { + CContactItem* cntItem = iCntDatabase->ReadMinimalContactLC( aContactId ); + CPEngContact* contactEntry = CPEngContact::NewL( cntItem ); // careful no in CleanUpStack + CleanupStack::PopAndDestroy( cntItem ); // cntItem + const MDesCArray& wvIds = contactEntry->WvIds(); + if ( ! wvIds.MdcaCount() ) + { + delete contactEntry; + return; + } + CleanupStack::PushL( contactEntry ); + iContacts.AppendL( contactEntry ); + CleanupStack::Pop( contactEntry ); + // update mapping, for each wv id + RemapWvIdsL( wvIds ); + } + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::RemoveContactL +// Remove contact from contact db cache +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngContactMapper::RemoveContactL( + TContactItemId& aContactId ) + { + TInt index( FindContact( aContactId ) ); + // if contact is in our cache, we can leave, nothing to do + if ( index == KErrNotFound ) + { + return; + } + CPEngContact* contact = iContacts[ index ]; + CleanupStack::PushL( contact ); + iContacts.Remove( index ); + RemapWvIdsL( contact->WvIds() ); + CleanupStack::PopAndDestroy( contact ); + } + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::UpdateContactL +// Update content of the contact in contact db cache +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngContactMapper::UpdateContactL( + TContactItemId& aContactId ) + { + TInt index( FindContact( aContactId ) ); + CPEngContact* contactEntry = NULL; + if ( index == KErrNotFound ) + { + // contact is not in the cache, try to add it + CContactItem* cntItem = iCntDatabase->ReadMinimalContactLC( aContactId ); + contactEntry = CPEngContact::NewL( cntItem ); // careful no in CleanUpStack + CleanupStack::PopAndDestroy( cntItem ); // cntItem + const MDesCArray& wvIds = contactEntry->WvIds(); + TInt wvIdCount( wvIds.MdcaCount() ); + if ( !wvIdCount ) + { + delete contactEntry; + return; + } + CleanupStack::PushL( contactEntry ); + iContacts.AppendL( contactEntry ); + CleanupStack::Pop( contactEntry ); + RemapWvIdsL( contactEntry->WvIds() ); + } + else + { + // contact is in cache, update it, first store old wv ids + contactEntry = iContacts[ index ]; + const MDesCArray& oldIds = contactEntry->WvIds(); + TInt count ( oldIds.MdcaCount() ); + CDesCArray* oldWVIds = new( ELeave ) CDesCArrayFlat( count ); + CleanupStack::PushL( oldWVIds ); + for ( TInt x( 0 ) ; x < count ; ++x ) + { + oldWVIds->AppendL( oldIds.MdcaPoint( x ) ); + } + contactEntry->UpdateContactL( *iCntDatabase ); + + // does contact entry need have any wv ids or it can be removed + const MDesCArray& newIds = contactEntry->WvIds(); + TInt newCount( newIds.MdcaCount() ); + if ( ! newCount ) + { + iContacts.Remove( index ); + delete contactEntry; + } + else + { + // remove new wv ids from old ones if the are same + // so we avoid double remapping + for ( TInt x( 0 ) ; x < newCount ; ++x ) + { + TInt pos( 0 ); + if ( KErrNone == oldWVIds->Find( newIds.MdcaPoint( x ), pos ) ) + { + oldWVIds->Delete( pos ); + } + } + RemapWvIdsL( newIds ); + } + RemapWvIdsL( *oldWVIds ); + CleanupStack::PopAndDestroy( oldWVIds ); // + } + } + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::HandleMultipleChangesL +// More changes happened in the contact db +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngContactMapper::HandleMultipleChangesL() + { + // rebuild whole contact db and call on all contact list full re-mapping + RebuildContactDbCacheL(); + TInt count( iListObservers.Count() ); + for ( TInt x( 0 ) ; x < count ; ++x ) + { + iListObservers[ x ]->ReMappAllContactsL(); + } + } + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::UpdateMappingOnContactListsL +// Notify all list observers about wv Ids mapping change +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngContactMapper::UpdateMappingOnContactListsL( + const TDesC& aWVId, + const CContactIdArray* aContactIds ) + { + TInt count( iListObservers.Count() ); + for ( TInt x( 0 ) ; x < count ; ++x ) + { + iListObservers[ x ]->UpdateMappingL( aWVId, aContactIds ); + } + } + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::RebuildContactDbCacheL() +// Rebuild contact db cache +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngContactMapper::RebuildContactDbCacheL() + { + // check all contacts + _LIT( KWVStart, "" ); + // Specify in which fields search should be performed + CContactItemFieldDef* fieldToSearchIn = new ( ELeave ) CContactItemFieldDef(); + CleanupStack::PushL( fieldToSearchIn ); + fieldToSearchIn->AppendL( KPbkFieldWVIdMapping ); + fieldToSearchIn->AppendL( KPbkFieldIMAddress ); + // search in contact database + CContactIdArray* contactIds = iCntDatabase->FindLC( KWVStart, + fieldToSearchIn ); + + // OK now we have Contact Ids, time to add contacts to cache + // reset our array + iContacts.ResetAndDestroy(); + CPEngContact* contact = NULL; + CContactItem* contactItem = NULL; + TInt count ( contactIds->Count() ); + for ( TInt x( 0 ) ; x < count ; x++ ) + { + contactItem = iCntDatabase->ReadMinimalContactLC( ( *contactIds )[ x ] ); + contact = CPEngContact::NewLC( contactItem ); + // store back up of the contact only if there was some id + if ( contact->WvIds().MdcaCount() ) + { + iContacts.AppendL( contact ); + CleanupStack::Pop( contact ); // contact + } + else + { + CleanupStack::PopAndDestroy( contact ); // contact + } + CleanupStack::PopAndDestroy( contactItem ); // contactItem + } + CleanupStack::PopAndDestroy( 2 ); // contactIDArray, fieldToSearchIn + } + + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::FindContact +// Find Contact in contact cache +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CPEngContactMapper::FindContact( + TContactItemId& aContactId ) const + { + TInt count ( iContacts.Count() ); + for ( TInt x( 0 ) ; x < count ; ++x ) + { + if ( iContacts[ x ]->ContactId() == aContactId ) + { + return x; + } + } + return KErrNotFound; + } + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::RemapWvIdsL +// Remap given wv Ids +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPEngContactMapper::RemapWvIdsL( const MDesCArray& aWVIds ) + { + TInt count( aWVIds.MdcaCount() ); + for ( TInt x( 0 ) ; x < count ; ++x ) + { + CContactIdArray* contactIds = + MapWvIdToContactIdLC( aWVIds.MdcaPoint( x ) ); + UpdateMappingOnContactListsL( aWVIds.MdcaPoint( x ), contactIds ); + CleanupStack::PopAndDestroy( contactIds ); // contactIds + } + } + + +// ----------------------------------------------------------------------------- +// CPEngContactMapper::FindListObserver +// Find Contact list observer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CPEngContactMapper::FindListObserver( + const CPEngNWSessionSlotID2& aSessionId ) const + { + TInt count( iListObservers.Count() ); + for ( TInt x( 0 ) ; x < count ; ++x ) + { + if ( KErrNone + == + iListObservers[ x ]->SessionId().MatchBasePart( aSessionId ) + ) + { + return x; + } + } + return KErrNotFound; + } + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + + +// End of File