PECengine/ListLibrary2/ContactListSrc/CPEngContactListModBase.cpp
changeset 0 094583676ce7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PECengine/ListLibrary2/ContactListSrc/CPEngContactListModBase.cpp	Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,1328 @@
+/*
+* 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:  Contact list model implementation
+*
+*/
+
+// INCLUDE FILES
+#include    "CPEngContactListModBase.h"
+
+#include    "CPEngContactListModItemContainer.h"
+#include    "CPEngContactListModChangeMonitor.h"
+#include    "CPEngContactListSettings.h"
+#include    "MPEngContactListSettingsManager.h"
+#include    "MPEngAttributeList2.h"
+#include    "MPEngStorageManager.h"
+#include    "PEngListLibraryPanics.h"
+#include    "PEngContactIdsTools.h"
+#include    "PresenceDebugPrint.h"
+
+#include    <e32std.h>
+#include    <bamdesca.h>
+
+
+
+// CONSTANTS
+
+// 1001 -  initial version
+// 1002 -  store of the delta and monitor have now length of wv IDs,
+static const TInt KListStoreVersion = 1002;
+
+
+// Minimal size of the store entry for contact list model
+// count of permanent,cached, and 2 change monitor arrays
+static const TInt KListStoreMinSize = 16;
+
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::CPEngContactListModBase()
+// -----------------------------------------------------------------------------
+//
+CPEngContactListModBase::CPEngContactListModBase(
+    CPEngContactListSettings& aListSettings,
+    MPEngContactListSettingsManager& aCntLstSettingsManager )
+        : CPEngStoreEntry( StoreTypeForListType( aListSettings.BaseSettings().iContactListType ) ),
+        iAccessCount( 1 ), // set initial access count to 1
+        iSettings( &aListSettings ),
+        iCntLstSettingsManager ( aCntLstSettingsManager )
+    {
+    iSize = KListStoreMinSize;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ConstructL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::ConstructL( MPEngStorageManager& aStorageManager )
+    {
+    iStorageId = iSettings->Name().AllocL();
+    iStorageId->Des().Fold();
+    BaseConstructL( aStorageManager );      // CSI: 9 #
+
+    iChangesMonitor = CPEngContactListModChangeMonitor::NewL( *this );
+
+    iStorageManager->RetrieveL( *this );
+
+    iCntLstSettingsManager.AddContactListSettingsObserverL( this );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::NewL()
+// -----------------------------------------------------------------------------
+//
+CPEngContactListModBase* CPEngContactListModBase::NewL(
+    CPEngContactListSettings& aListSettings,
+    MPEngStorageManager& aStorageManager,
+    MPEngContactListSettingsManager& aCntLstSettingsManager )
+    {
+    CPEngContactListModBase* self = NewLC( aListSettings,
+                                           aStorageManager,
+                                           aCntLstSettingsManager );
+
+    CleanupStack::Pop();
+    return self;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::NewL()
+// -----------------------------------------------------------------------------
+//
+CPEngContactListModBase* CPEngContactListModBase::NewLC(
+    CPEngContactListSettings& aListSettings,
+    MPEngStorageManager& aStorageManager,
+    MPEngContactListSettingsManager& aCntLstSettingsManager )
+    {
+    PENG_DP( D_PENG_LIT( "CPEngContactListModBase::NewLC() - %S" ),
+             &aListSettings.Name() ) ;
+
+    CPEngContactListModBase* self = new ( ELeave )
+    CPEngContactListModBase( aListSettings,
+                             aCntLstSettingsManager );
+
+    CleanupClosePushL( *self );
+    self->ConstructL( aStorageManager );
+
+    return self;
+    }
+
+
+// Destructor
+CPEngContactListModBase::~CPEngContactListModBase()
+    {
+    PENG_DP( D_PENG_LIT( "CPEngContactListModBase::~CPEngContactListModBase" ) ) ;
+
+    // panic if object is still accessed
+    __ASSERT_DEBUG( iAccessCount == 0 , Panic( ERefAccessedObjectDeleted ) );
+
+
+    iCntLstSettingsManager.RemoveContactListSettingsObserver( this );
+    iCntLstSettingsManager.RemoveModel( this );
+
+    ResetLocalView();
+    ResetNetworkView();
+
+    iServerOrder.Reset();
+
+    delete iChangesMonitor;
+    delete iStorageId;
+    }
+
+
+
+// =============================================================================
+// ===============Functions of MPEngContactListAdvance class ===================
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ContactItemAdvance()
+// -----------------------------------------------------------------------------
+//
+MPEngContactItemAdvance& CPEngContactListModBase::ContactItemAdvance(
+    TInt aIndex,
+    TPEngContactListView aView )
+    {
+    switch ( aView )
+        {
+        case EPEngCntListLocalView:
+            {
+            return *( iLocalView[ aIndex ] );
+            }
+
+        case EPEngCntListNetworkView:
+            {
+            return *( iNetworkView[ aIndex ] );
+            }
+
+        default:
+            {
+            Panic( EWrongViewId );
+            return *( iNetworkView[ aIndex ] );
+            }
+        }
+    }
+
+
+
+// =============================================================================
+// ===============Functions of MPEngContactList2 class =========================
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::AddContactL()
+// -----------------------------------------------------------------------------
+//
+TInt CPEngContactListModBase::AddContactL( const TDesC& aContact,
+                                           const TDesC& aNickName )
+    {
+    PENG_DP( D_PENG_LIT( "CPEngContactListModBase::AddIdL: %S, : %S" ),
+             &this->StorageId(), &aContact );
+
+    LeaveIfListUpdateInProgressL();
+    iChangesMonitor->Reset();
+
+    // Check if contact exists in the local list view
+    TInt pos( KErrNotFound );
+    if ( KErrNotFound != DoFindContact( iLocalView, aContact, pos ) )
+        {
+        // Contact already exists, leave
+        User::Leave( KErrAlreadyExists );
+        }
+
+    // does contact exists in the network view
+    TInt index ( DoFindContact( iNetworkView, aContact ) );
+    if ( index != KErrNotFound )
+        {
+        // contact already exist on the network, it was probably removed
+        // and now it is added, update nick name and reference
+        iNetworkView[ index ]->UpdateNickNameL( aNickName );
+        iLocalView.InsertL( iNetworkView[ index ], pos );
+        iLocalView[ pos ]->Open( CPEngContactListModItemContainer::ELocalRef );
+        }
+
+    else
+        {
+        // Contact does not exist in any view, add it to the local one
+        CPEngContactListModItemContainer* contact =
+            CPEngContactListModItemContainer::NewNewNickLC( *this,
+                                                            aContact,
+                                                            aNickName );
+
+        contact->SetFreshContact( ETrue );
+        iLocalView.InsertL( contact, pos );
+        iLocalView[ pos ]->Open( CPEngContactListModItemContainer::ELocalRef );
+        CleanupStack::PopAndDestroy(); // contact
+        }
+
+
+    StoreContactListL();
+    return pos;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::RemoveContactL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::RemoveContactL( const TDesC& aContact )
+    {
+    PENG_DP( D_PENG_LIT( "CPEngContactListModBase::RemoveIdL - %S : %S " ),
+             &this->StorageId(), &aContact );
+
+    LeaveIfListUpdateInProgressL();
+    iChangesMonitor->Reset();
+
+    // does contact exist in the local view?
+    TInt pos( DoFindContact( iLocalView, aContact ) );
+    if ( pos == KErrNotFound )
+        {
+        // nothing to delete
+        return;
+        }
+
+
+    iLocalView[ pos ]->CloseRef( CPEngContactListModItemContainer::ELocalRef );
+    iLocalView.Remove( pos );
+
+    StoreContactListL();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::FindContact()
+// -----------------------------------------------------------------------------
+//
+TInt CPEngContactListModBase::FindContact( const TDesC& aContact,
+                                           TPEngContactListView aView ) const
+    {
+    switch ( aView )
+        {
+        case EPEngCntListLocalView:
+            {
+            return DoFindContact( iLocalView, aContact );
+            }
+
+        case EPEngCntListNetworkView:
+            {
+            return DoFindContact( iNetworkView, aContact );
+            }
+
+        case EPEngAddedContacts:
+            {
+            const TDesC& domain = iCntLstSettingsManager.UserDomain();
+            return iChangesMonitor->FindContactIdInAdded( aContact, domain );
+            }
+
+        case EPEngRemovedContacts:
+            {
+            const TDesC& domain = iCntLstSettingsManager.UserDomain();
+            return iChangesMonitor->FindContactIdInRemoved( aContact, domain );
+            }
+
+        default:
+            {
+            Panic( EWrongViewId );
+            return KErrNotFound;
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::Count()
+// -----------------------------------------------------------------------------
+//
+TInt CPEngContactListModBase::Count( TPEngContactListView aView ) const
+    {
+    switch ( aView )
+        {
+        case EPEngCntListLocalView:
+            {
+            return iLocalView.Count();
+            }
+
+        case EPEngCntListNetworkView:
+            {
+            return iNetworkView.Count();
+            }
+
+        case EPEngAddedContacts:
+            {
+            return iChangesMonitor->CountAddedContactIds();
+            }
+
+        case EPEngRemovedContacts:
+            {
+            return iChangesMonitor->CountRemovedContactIds();
+            }
+
+        default:
+            {
+            Panic( EWrongViewId );
+            return 0;
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ContactItem()
+// -----------------------------------------------------------------------------
+//
+MPEngContactItem& CPEngContactListModBase::ContactItem( TInt aIndex,
+                                                        TPEngContactListView aView )
+    {
+    return ContactItemAdvance( aIndex, aView );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ContactItem()
+// -----------------------------------------------------------------------------
+//
+const MPEngContactItem& CPEngContactListModBase::ContactItem(
+    TInt aIndex,
+    TPEngContactListView aView ) const
+    {
+    switch ( aView )
+        {
+        case EPEngCntListLocalView:
+            {
+            return *( iLocalView[ aIndex ] );
+            }
+
+        case EPEngCntListNetworkView:
+            {
+            return *( iNetworkView[ aIndex ] );
+            }
+
+        default:
+            {
+            Panic( EWrongViewId );
+            return *( iNetworkView[ aIndex ] );
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::RemovedContacts()
+// -----------------------------------------------------------------------------
+//
+const MDesCArray& CPEngContactListModBase::RemovedContacts( ) const
+    {
+    return iChangesMonitor->RemovedContactIds();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::AddedContacts()
+// -----------------------------------------------------------------------------
+//
+const MDesCArray& CPEngContactListModBase::AddedContacts( ) const
+    {
+    return iChangesMonitor->AddedContactIds();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ListProperties()
+// -----------------------------------------------------------------------------
+//
+MPEngContactListProperties& CPEngContactListModBase::ListProperties()
+    {
+    return *iSettings;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::RemoveAllContactIdsL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::RemoveAllContactsL()
+    {
+    // reset local view and leave only network view
+    ResetLocalView();
+    StoreContactListL();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::SuspendUpdateNotification()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::SuspendUpdateNotification()
+    {
+    BufferServerSideNotifications();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ReleaseUpdateNotification()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::ReleaseUpdateNotification()
+    {
+    ReleaseServerSideBuffering();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::RollBackAllChangesL()
+// -----------------------------------------------------------------------------
+//
+TInt CPEngContactListModBase::RollBackAllChangesL()
+    {
+    LeaveIfListUpdateInProgressL();
+
+    RollbackL();
+
+    return KErrNone;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::UpdateInProgress()
+// -----------------------------------------------------------------------------
+//
+TBool CPEngContactListModBase::UpdateInProgress() const
+    {
+    return iStorageManager->Locked( *this, EStorageLockLevelHigh );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::UpdateInProgress()
+// -----------------------------------------------------------------------------
+//
+TBool CPEngContactListModBase::UpdateRequired() const
+    {
+    TInt countLoc( iLocalView.Count() );
+    TInt countNet( iNetworkView.Count() );
+    if ( countLoc != countNet )
+        {
+        return ETrue;
+        }
+    for ( TInt x( 0 ) ; x < countLoc ; ++x )
+        {
+        if ( ( KErrNotFound == iNetworkView.Find( iLocalView[ x ] ) )
+             ||
+             ( iLocalView[ x ]->NewNick() )
+           )
+            {
+            return ETrue;
+            }
+        }
+    for ( TInt i( 0 ) ; i < countNet ; ++i )
+        {
+        if  ( KErrNotFound == iLocalView.Find( iNetworkView[ i ] ) )
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+
+
+// =============================================================================
+// ===============Functions of CPEngStoreEntry class ===========================
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ExternalizeL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::ExternalizeL( RWriteStream& aStream,
+                                            TPEngStorageType aStorageType ) const
+    {
+    // what is the type of the list, if it is not mixed store all at once
+    if ( EPEngMixedCachedVersionCon == StorageType() )
+        {
+        // whole list is cached, store it all
+        ExternalizeContactsL( aStream, EPEngStorageBasicPermanent );
+        ExternalizeContactsL( aStream, EPEngStorageBasicCached );
+        iChangesMonitor->ExternalizeArrayL( aStream );
+        return;
+        }
+
+
+    // write asked part
+    switch ( aStorageType )
+        {
+        case EPEngStorageBasicPermanent:
+            {
+            // first write version of the storage
+            aStream.WriteInt32L( KListStoreVersion );
+
+            // store permanent part of the contact list
+            ExternalizeContactsL( aStream, aStorageType );
+            break;
+            };
+
+
+        case EPEngStorageBasicCached:
+            {
+            // store cached part of the contact list
+            ExternalizeContactsL( aStream, aStorageType );
+            iChangesMonitor->ExternalizeArrayL( aStream );
+            break;
+            }
+
+
+        default:
+            {
+            break;
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::InternalizeL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::InternalizeL( RReadStream& aStream,
+                                            TPEngStorageType aStorageType )
+    {
+    // what is the type of the list, if it is not mixed read all at once
+    if ( EPEngMixedCachedVersionCon == StorageType() )
+        {
+        // whole list is cached, retrieve it once
+        Reset();
+        InternalizePermanentContactsL( aStream );
+        InternalizeCachedContactsL( aStream );
+        iChangesMonitor->InternalizeArrayL( aStream );
+        return;
+        }
+
+
+    // read offered part
+    switch ( aStorageType )
+        {
+        case EPEngStorageBasicPermanent:
+            {
+            // read permanent part of the contact list
+            // fist check version
+            Reset();
+            if ( KListStoreVersion != aStream.ReadInt32L() )
+                {
+                // Version is wrong, remove file from store and reset
+                iStorageManager->Delete( *this );
+                return;
+                }
+
+            // now internalize all permanent parts
+            InternalizePermanentContactsL( aStream );
+            break;
+            }
+
+
+        case EPEngStorageBasicCached:
+            {
+            // read cached part of the contact list
+            InternalizeCachedContactsL( aStream );
+            iChangesMonitor->InternalizeArrayL( aStream );
+            break;
+            }
+
+
+        default:
+            {
+            break;
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::StorageId()
+// -----------------------------------------------------------------------------
+//
+const TDesC& CPEngContactListModBase::StorageId() const
+    {
+    return *iStorageId;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::EntrySize()
+// -----------------------------------------------------------------------------
+//
+TUint32 CPEngContactListModBase::EntrySize() const
+    {
+    return iSize;
+    }
+
+
+
+// =============================================================================
+// ===============Functions of MPEngSIDChangeObserver ==========================
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::HandleSIDsChangeL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::HandleSIDsChangeL( CPtrCArray& /* aChangedSIDs */ )
+    {
+    TInt err( iStorageManager->RetrieveL( *this ) );
+    if ( err == KErrNotFound )
+        {
+        Reset();
+        return;
+        }
+
+    if ( err != KErrNone )
+        {
+        iStorageManager->Delete( *this );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::HandleSIDNotifyError()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::HandleSIDNotifyError( TInt /* aError */ )
+    {
+    Reset();
+    }
+
+
+
+// =============================================================================
+// ===============Functions of MPEngContactListModStore ========================
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::StoreSizeCount()
+// -----------------------------------------------------------------------------
+//
+TInt& CPEngContactListModBase::StoreSizeCount()
+    {
+    return iSize;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::StoreEntryL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::StoreEntryL()
+    {
+    StoreL();
+    }
+
+
+
+
+// =============================================================================
+// ===============Functions of MPEngContactListSettingsObserver class ==========
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::RefreshSettingsReference()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::RefreshSettingsReference()
+    {
+    iSettings = iCntLstSettingsManager.ContactListSettingsOrNull( StorageId() );
+    }
+
+
+
+// =============================================================================
+// ===============Functions of main class ======================================
+// =============================================================================
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::StoreTypeForListType()
+// -----------------------------------------------------------------------------
+//
+TPEngStorageType CPEngContactListModBase::StoreTypeForListType(
+    TPEngContactListType aListType )
+    {
+    return ( aListType == EPEngCachedContactList ) ? EPEngMixedCachedVersionCon :
+           EPEngMixedPermanentCachedVersionCon;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::Open()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::Open()
+    {
+    iAccessCount++;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::Close()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::Close()
+    {
+    iAccessCount--;
+
+    if ( iAccessCount == 0 )
+        {
+        delete this;
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::StoreContactListL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::StoreContactListL()
+    {
+    TRAPD( err, iStorageManager->StoreL( *this ) ) ;
+    if ( err != KErrNone )
+        {
+        if ( err == KErrDiskFull )
+            {
+            if ( KErrNotFound == iStorageManager->RetrieveL( *this ) )
+                {
+                Reset();
+                }
+            }
+
+        User::Leave( err );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::FillAddNickListL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::FillAddNickListL(
+    RPointerArray<CPEngContactListModItemContainer>& aAddNickList )
+    {
+    TInt count( iLocalView.Count() );
+    for ( TInt x( 0 ) ; x < count ; ++x )
+        {
+        if ( ( KErrNotFound == iNetworkView.Find( iLocalView[ x ] ) ) ||
+             ( iLocalView[ x ]->NewNick() ) )
+            {
+            aAddNickList.AppendL( iLocalView[ x ] );
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::FillRemoveNickListL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::FillRemoveNickListL(
+    RPointerArray<CPEngContactListModItemContainer>& aRemoveNickList )
+    {
+    TInt count( iNetworkView.Count() );
+    for ( TInt x( 0 ) ; x < count ; ++x )
+        {
+        if ( KErrNotFound == iLocalView.Find( iNetworkView[ x ] ) )
+            {
+            aRemoveNickList.AppendL( iNetworkView[ x ] );
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::CommitAddContactsL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::CommitAddContactsL()
+    {
+    TInt count( iLocalView.Count() );
+    for ( TInt x( 0 ) ; x < count ; ++x )
+        {
+        iLocalView[ x ]->CommitNickName();
+        iLocalView[ x ]->SetFreshContact( EFalse );
+
+        if ( KErrNotFound == iNetworkView.Find( iLocalView[ x ] ) )
+            {
+            TInt pos( KErrNotFound );
+            CPEngContactListModItemContainer* cnt = iLocalView[ x ];
+            DoFindContact( iNetworkView, cnt->Id(), pos );
+
+            iNetworkView.InsertL( cnt, pos );
+            cnt->Open( CPEngContactListModItemContainer::ENetworkRef ); // CSI: 65 #
+
+            // no order, add to the end
+            cnt->SetServerIndex( iServerOrder.Count() );
+            iServerOrder.AppendL( cnt );
+
+            // add contact also to the added
+            iChangesMonitor->InsertAddedContactIdL( cnt->Id() );
+            }
+        }
+
+    StoreL();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::CommitRemoveContactsL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::CommitRemoveContactsL()
+    {
+    for ( TInt x( iNetworkView.Count() - 1 ) ; x >= 0 ; --x )
+        {
+        if ( KErrNotFound == iLocalView.Find( iNetworkView[ x ] ) )
+            {
+            CPEngContactListModItemContainer* contact = iNetworkView[ x ];
+
+            // cache the index that's being removed
+            TInt serverIndex = contact->ServerIndex();
+
+            // add contact also to the removed
+            iChangesMonitor->InsertRemovedContactIdL( contact->Id() );
+
+            // remove from the network ordered
+            // let it panic, if not found
+            // arrays should be always in sync
+            iServerOrder.Remove( iServerOrder.Find( contact ) );
+
+            contact->CloseRef( CPEngContactListModItemContainer::ENetworkRef );
+
+            iNetworkView.Remove( x );
+
+            // and reorganize iNetworkView's server indexes
+            ReorganizeServerIndexOrder( serverIndex );
+            }
+        }
+
+    StoreL();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::RollbackL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::RollbackL()
+    {
+    // reset local list and add there items from the network one
+    ResetLocalView();
+
+    TInt count( iNetworkView.Count() );
+    for ( TInt x( 0 ) ; x < count ; ++x )
+        {
+        iLocalView.AppendL( iNetworkView[ x ] );
+        iNetworkView[ x ]->Open( CPEngContactListModItemContainer::ELocalRef );
+        iNetworkView[ x ]->RollBackNickname();
+        }
+
+    StoreContactListL();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::FindContactInAll()
+// -----------------------------------------------------------------------------
+//
+CPEngContactListModItemContainer* CPEngContactListModBase::FindContactInAll(
+    const TDesC& aContact )
+    {
+    TInt index ( DoFindContact( iLocalView, aContact ) );
+    if ( index != KErrNotFound )
+        {
+        return iLocalView[ index ];
+        }
+
+    index = DoFindContact( iNetworkView, aContact );
+    if ( index != KErrNotFound )
+        {
+        return iNetworkView[ index ];
+        }
+
+    return NULL;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ContactExistsOnServer()
+// -----------------------------------------------------------------------------
+//
+TBool CPEngContactListModBase::ContactExistsOnServer(
+    CPEngContactListModItemContainer& aContact )
+    {
+    return aContact.RefActive( CPEngContactListModItemContainer::ENetworkRef );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::AdoptNewContactsL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::AdoptNewContactsL(
+    RPointerArray<CPEngContactListModItemContainer>& aContacts )
+    {
+    ResetLocalView();
+    ResetNetworkView();
+
+    TInt count = aContacts.Count();
+    for ( TInt ii( 0 ) ; ii < count ; ++ii )
+        {
+        // take always first in array
+        CPEngContactListModItemContainer* cnt = aContacts[ 0 ];
+        iLocalView.AppendL( cnt );
+        cnt->Open( CPEngContactListModItemContainer::ELocalRef );   // CSI: 65 #
+        iNetworkView.AppendL( cnt );
+        cnt->Open( CPEngContactListModItemContainer::ENetworkRef ); // CSI: 65 #
+        iServerOrder.AppendL( NULL );
+        aContacts.Remove( 0 );
+        cnt->Close();
+        }
+
+
+    RestoreServerOrderedArray();
+    StoreL();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::AdoptNetworkViewL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::AdoptNetworkViewL(
+    RPointerArray<CPEngContactListModItemContainer>& aContacts )
+    {
+    ResetNetworkView();
+
+    TInt count( aContacts.Count() );
+    for ( TInt x( 0 ) ; x < count ; ++x )
+        {
+        // take always first in array
+        CPEngContactListModItemContainer* cnt = aContacts[ 0 ];
+        iNetworkView.AppendL( cnt );
+        cnt->Open( CPEngContactListModItemContainer::ENetworkRef );     // CSI: 65 #
+        iServerOrder.AppendL( NULL );
+        aContacts.Remove( 0 );
+        cnt->Close();
+        }
+
+    RestoreServerOrderedArray();
+    StoreL();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::RemoveBadContactL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::RemoveBadContactL( const TDesC& aContact )
+    {
+    iChangesMonitor->InsertRemovedContactIdL( aContact );
+    iChangesMonitor->RemoveAddedContactId( aContact );
+
+    CPEngContactListModItemContainer* cnt = FindContactInAll( aContact );
+
+
+    if ( cnt && cnt->RefActive( CPEngContactListModItemContainer::ENetworkRef ) )
+        {
+        TInt serverIndex = cnt->ServerIndex();
+
+        iNetworkView.Remove( iNetworkView.Find( cnt ) );
+        cnt = cnt->CloseRef( CPEngContactListModItemContainer::ENetworkRef );
+        iServerOrder.Remove( iServerOrder.Find( cnt ) );
+
+        // and reorganize iNetworkView's server indexes
+        ReorganizeServerIndexOrder( serverIndex );
+        }
+
+
+    if ( cnt && cnt->RefActive( CPEngContactListModItemContainer::ELocalRef ) )
+        {
+        iLocalView.Remove( iLocalView.Find( cnt ) );
+        cnt->CloseRef( CPEngContactListModItemContainer::ELocalRef );
+        }
+
+    StoreL();
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::Reset()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::Reset()
+    {
+    ResetLocalView();
+    ResetNetworkView();
+    iChangesMonitor->Reset();
+
+    iSize = KListStoreMinSize;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ResetLocalView()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::ResetLocalView()
+    {
+    TInt count( iLocalView.Count() );
+    for ( TInt x( 0 ) ; x < count ; ++x )
+        {
+        iLocalView[ x ]->CloseRef( CPEngContactListModItemContainer::ELocalRef );
+        }
+
+    iLocalView.Reset();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ResetNetworkView()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::ResetNetworkView()
+    {
+    TInt count( iNetworkView.Count() );
+    for ( TInt x( 0 ) ; x < count ; ++x )
+        {
+        iNetworkView[ x ]->CloseRef( CPEngContactListModItemContainer::ENetworkRef );
+        }
+
+    iNetworkView.Reset();
+    iServerOrder.Reset();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::LeaveIfListUpdateInProgressL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::LeaveIfListUpdateInProgressL() const
+    {
+    if ( UpdateInProgress() )
+        {
+        User::Leave( KErrInUse );
+        }
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ChangeMonitor()
+// -----------------------------------------------------------------------------
+//
+CPEngContactListModChangeMonitor& CPEngContactListModBase::ChangeMonitor()
+    {
+    return *iChangesMonitor;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::Settings()
+// -----------------------------------------------------------------------------
+//
+CPEngContactListSettings& CPEngContactListModBase::Settings()
+    {
+    return *iSettings;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ServerOrderedContacts()
+// -----------------------------------------------------------------------------
+//
+const RPointerArray<CPEngContactListModItemContainer>&
+CPEngContactListModBase::ServerOrderedContacts() const
+    {
+    return iServerOrder;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::DoFindContact()
+// -----------------------------------------------------------------------------
+//
+TInt CPEngContactListModBase::DoFindContact(
+    const RPointerArray<CPEngContactListModItemContainer>& aArray,
+    const TDesC& aContact,
+    TInt& aIndex,
+    TBool aFirstPrefered /* EFalse */ ) const
+    {
+    const TDesC& domain = iCntLstSettingsManager.UserDomain();
+    TInt high( aArray.Count() );
+
+
+    if ( !high ||
+         ( aFirstPrefered && 0 > NContactIdsTools::CompareContactIds( aContact,
+                                                                      aArray[ 0 ]->Id(),
+                                                                      domain ) ) )
+        {
+        aIndex = 0;
+        return KErrNotFound;
+        }
+
+
+    TInt low( 0 );
+    TInt ret( KErrNotFound );
+    while ( high > low )
+        {
+        TInt inx = ( low + high ) >> 1;
+        TInt k ( NContactIdsTools::CompareContactIds( aContact,
+                                                      aArray[ inx ]->Id(),
+                                                      domain ) );
+        if ( k == 0 )
+            {
+            aIndex = inx;
+            return KErrNone;
+            }
+        else if ( k > 0 )
+            low = inx + 1;
+        else
+            high = inx;
+        }
+    aIndex = high;
+    return ret;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::DoFindContact()
+// -----------------------------------------------------------------------------
+//
+TInt CPEngContactListModBase::DoFindContact(
+    const RPointerArray<CPEngContactListModItemContainer>& aArray,
+    const TDesC& aContact ) const
+    {
+    TInt index( KErrNotFound );
+    TInt err( DoFindContact( aArray, aContact, index ) );
+    if ( err != KErrNotFound )
+        {
+        return index;
+        }
+
+    return KErrNotFound;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ExternalizeContactsL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::ExternalizeContactsL( RWriteStream& aStream,
+                                                    TPEngStorageType aStorageType ) const
+    {
+    TInt count( iLocalView.Count() );
+    for ( TInt x( 0 ) ; x < count  ; ++x )
+        {
+        aStream.WriteInt32L( KErrNone );
+        iLocalView[ x ]->ExternalizeL( aStream, aStorageType );
+        }
+
+    count = iNetworkView.Count();
+    for ( TInt y( 0 ) ; y < count ; ++y )
+        {
+        if ( !iNetworkView[ y ]->RefActive( CPEngContactListModItemContainer::ELocalRef ) )
+            {
+            aStream.WriteInt32L( KErrNone );
+            iNetworkView[ y ]->ExternalizeL( aStream, aStorageType );
+            }
+        }
+
+    aStream.WriteInt32L( KErrNotFound );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::InternalizePermanentContactsL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::InternalizePermanentContactsL( RReadStream& aStream )
+    {
+    CPEngContactListModItemContainer* contact = NULL;
+
+    while ( KErrNone == aStream.ReadInt32L() )
+        {
+        contact = CPEngContactListModItemContainer::NewLC( *this, aStream );
+
+        if ( contact->RefActive( CPEngContactListModItemContainer::ELocalRef ) )
+            {
+            iLocalView.AppendL( contact );
+            contact->Open( CPEngContactListModItemContainer::ELocalRef ); // CSI: 65 #
+            }
+
+        if ( contact->RefActive( CPEngContactListModItemContainer::ENetworkRef ) )
+            {
+            iNetworkView.AppendL( contact );
+            contact->Open( CPEngContactListModItemContainer::ENetworkRef ); // CSI: 65 #
+            iServerOrder.AppendL( NULL );
+            }
+
+        CleanupStack::PopAndDestroy(); // contact
+        }
+
+    RestoreServerOrderedArray();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::InternalizeCachedContactsL()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::InternalizeCachedContactsL( RReadStream& aStream )
+    {
+    TInt count( iLocalView.Count() );
+    for ( TInt x( 0 ) ; x < count ; ++x )
+        {
+        aStream.ReadInt32L(); // KErrNone
+        iLocalView[ x ]->InternalizeL( aStream, EPEngStorageBasicCached );
+        }
+
+    count = iNetworkView.Count();
+    for ( TInt y( 0 ) ; y < count ; ++y )
+        {
+        if ( ! iNetworkView[ y ]->RefActive( CPEngContactListModItemContainer::ELocalRef ) )
+            {
+            aStream.ReadInt32L(); // KErrNone
+            iNetworkView[ y ]->InternalizeL( aStream, EPEngStorageBasicCached );
+            }
+        }
+
+    aStream.ReadInt32L(); // KErrNotFound
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::RestoreServerOrderedArray()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::RestoreServerOrderedArray()
+    {
+    TInt count( iNetworkView.Count() );
+    for ( TInt x( 0 ) ; x < count ; ++x )
+        {
+        CPEngContactListModItemContainer* contact = iNetworkView[ x ];
+        __ASSERT_DEBUG( count > contact->ServerIndex() , Panic( ERefServerOrderedArrayNotFilled ) );
+        iServerOrder[ contact->ServerIndex() ] = contact;
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPEngContactListModBase::ReorganizeServerIndexOrder()
+// -----------------------------------------------------------------------------
+//
+void CPEngContactListModBase::ReorganizeServerIndexOrder( TInt aIndex )
+    {
+    TInt networkViewCount( iNetworkView.Count() );
+
+    for ( TInt ii( 0 ) ; ii < networkViewCount; ii++ )
+        {
+        TInt srvIndex( iNetworkView[ii]->ServerIndex() );
+        if ( srvIndex > aIndex )
+            {
+            srvIndex--;
+            iNetworkView[ii]->SetServerIndex( srvIndex );
+            }
+        }
+    }
+
+
+
+//  End of File
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+