PECengine/JanitorPlugin2/Src/CPEngContactMapper.cpp
changeset 0 094583676ce7
--- /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    <e32std.h>
+#include	<bamdesca.h>
+#include	<cntitem.h>
+
+#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> (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