cmmanager/cmmgr/cmmserver/src/cmmdestinationinstance.cpp
changeset 20 9c97ad6591ae
child 27 489cf6208544
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmmanager/cmmgr/cmmserver/src/cmmdestinationinstance.cpp	Mon May 03 12:53:07 2010 +0300
@@ -0,0 +1,1683 @@
+/*
+* Copyright (c) 2009-2010 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:
+* Session side object representing a destination.
+*
+*/
+
+
+#include <cmpluginbaseeng.h>
+#include <datamobilitycommsdattypes.h>
+#include <cmpluginembdestinationdef.h>
+
+#include "cmmdestinationinstance.h"
+#include "cmmsession.h"
+#include "cmmcache.h"
+#include "cmmconnmethodinstance.h"
+#include "cmmconnmethoditem.h"
+#include "cmmanagertextresolver.h"
+
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "cmmdestinationinstanceTraces.h"
+#endif
+
+
+// ---------------------------------------------------------------------------
+// Two phased construction.
+// ---------------------------------------------------------------------------
+//
+CCmmDestinationInstance* CCmmDestinationInstance::NewL( CCmmSession* aCmmSession, CCmmCache* aCache )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_NEWL_ENTRY );
+
+    CCmmDestinationInstance* self = CCmmDestinationInstance::NewLC( aCmmSession, aCache );
+    CleanupStack::Pop( self );
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_NEWL_EXIT );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Two phased construction.
+// ---------------------------------------------------------------------------
+//
+CCmmDestinationInstance* CCmmDestinationInstance::NewLC( CCmmSession* aCmmSession, CCmmCache* aCache )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_NEWLC_ENTRY );
+
+    CCmmDestinationInstance* self = new( ELeave ) CCmmDestinationInstance( aCmmSession, aCache );
+    CleanupClosePushL( *self );
+    self->ConstructL();
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_NEWLC_EXIT );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CCmmDestinationInstance::~CCmmDestinationInstance()
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_CCMMDESTINATIONINSTANCE_ENTRY );
+
+    // Tell cache this handle is beeing closed. Cache will update it's own
+    // bookkeeping accordingly.
+    if ( iCache )
+        {
+        iCache->CloseDestination( *this );
+        }
+    delete iNetworkRecord;
+    delete iDestApRecord;
+    delete iMetadataRecord;
+
+    iConnMethodItemArray.Close();
+    iConnMethodsToBeDeleted.Close();
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_CCMMDESTINATIONINSTANCE_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Constructor.
+// ---------------------------------------------------------------------------
+//
+CCmmDestinationInstance::CCmmDestinationInstance(
+        CCmmSession* aCmmSession,
+        CCmmCache* aCache )
+        :
+        iCmmSession( aCmmSession ),
+        iCache( aCache )
+    {
+    OstTraceFunctionEntry0( DUP1_CCMMDESTINATIONINSTANCE_CCMMDESTINATIONINSTANCE_ENTRY );
+
+    iNetworkRecord = NULL;
+    iDestApRecord = NULL;
+    iMetadataRecord = NULL;
+
+    iNetworkRecordStatus = ECmmRecordStatusBlank;
+    iDestApRecordStatus = ECmmRecordStatusBlank;
+    iMetadataRecordStatus = ECmmRecordStatusBlank;
+
+    iStatus = ECmmDestinationStatusChanged;
+    iId = 0;
+    iHandle = 0;
+
+    iProtectionChanged = EFalse;
+    iLastProtectionLevel = CMManager::EProtLevel0;
+    iCurrentProtectionLevel = CMManager::EProtLevel0;
+
+    OstTraceFunctionExit0( DUP1_CCMMDESTINATIONINSTANCE_CCMMDESTINATIONINSTANCE_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Second phase constructor.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::ConstructL()
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_CONSTRUCTL_ENTRY );
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_CONSTRUCTL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Set the destination ID.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetId( const TUint32& aId )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETID_ENTRY );
+
+    iId = aId;
+
+    // If this is the real ID (not the temporary ID of a new unsaved destination),
+    // write it also into network record.
+    if ( aId > KCmmDestIdIntervalMin && aId < KCmmDestIdIntervalMax )
+        {
+        iNetworkRecord->SetRecordId( aId - KCmDefaultDestinationAPTagId );
+        iDestApRecord->iRecordTag = aId;
+        iDestApRecord->iCustomSelectionPolicy = ( aId - KCmDefaultDestinationAPTagId );
+        iMetadataRecord->iSNAP = aId;
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETID_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Get the destination ID.
+// ---------------------------------------------------------------------------
+//
+TUint32 CCmmDestinationInstance::GetId() const
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETID_ENTRY );
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETID_EXIT );
+    return iId;
+    }
+
+// ---------------------------------------------------------------------------
+// Set the current status of this destination.
+// ECmmDestinationStatusValid: Contents in sync with database.
+// ECmmDestinationStatusChanged: Contents differ from database contents.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetStatus( const TCmmDestinationStatus& aStatus )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETSTATUS_ENTRY );
+
+    switch ( aStatus )
+        {
+        // Fallthrough intended
+        case ECmmDestinationStatusValid:
+        case ECmmDestinationStatusChanged:
+            iStatus = aStatus;
+            break;
+        default:
+            ASSERT(0); // Error, invalid status.
+            break;
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETSTATUS_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Gets the current status of this destination instance.
+// ---------------------------------------------------------------------------
+//
+TCmmDestinationStatus CCmmDestinationInstance::GetStatus() const
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETSTATUS_ENTRY );
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETSTATUS_EXIT );
+    return iStatus;
+    }
+
+// ---------------------------------------------------------------------------
+// Get handle ID.
+// ---------------------------------------------------------------------------
+//
+TInt CCmmDestinationInstance::GetHandle() const
+    {
+    return iHandle;
+    }
+
+// ---------------------------------------------------------------------------
+// Set handle ID.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetHandle( const TInt& aHandle )
+    {
+    iHandle = aHandle;
+    }
+
+// ---------------------------------------------------------------------------
+// Set the record status for all records.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetStatusForAllRecords( const TCmmRecordStatus& aStatus )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETSTATUSFORALLRECORDS_ENTRY );
+
+    iDestApRecordStatus = aStatus;
+    iNetworkRecordStatus = aStatus;
+    iMetadataRecordStatus = aStatus;
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETSTATUSFORALLRECORDS_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Get the destination element ID.
+// ---------------------------------------------------------------------------
+//
+TUint32 CCmmDestinationInstance::GetElementIdL()
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETELEMENTIDL_ENTRY );
+
+    RefreshRecordL( ECmmDestNetworkRecord );
+
+    if ( !iNetworkRecord )
+        {
+        User::Leave( KErrCorrupt );
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETELEMENTIDL_EXIT );
+    return iNetworkRecord->ElementId() & KCDMaskShowField;
+    }
+
+// ---------------------------------------------------------------------------
+// Get the destination access point record's record tag (destination ID).
+// ---------------------------------------------------------------------------
+//
+TUint32 CCmmDestinationInstance::GetRecordTagFromApRecordL()
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETRECORDTAGFROMAPRECORDL_ENTRY );
+
+    RefreshRecordL( ECmmDestApRecord );
+
+    if ( !iDestApRecord )
+        {
+        User::Leave( KErrCorrupt );
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETRECORDTAGFROMAPRECORDL_EXIT );
+    return iDestApRecord->iRecordTag;
+    }
+
+// ---------------------------------------------------------------------------
+// Sets a record pointer to the one given as parameter, Ownership is
+// transfered. Also deletes the previous pointer and sets the record status
+// to 'ECmmRecordStatusLoaded'.
+// ---------------------------------------------------------------------------
+//
+TInt CCmmDestinationInstance::SetRecordPointer(
+        const TCmmDbRecords& aDestRecord,
+        CommsDat::CCDRecordBase* aRecordPointer )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETRECORDPOINTER_ENTRY );
+
+    TInt ret( KErrNone );
+    switch ( aDestRecord )
+        {
+        case ECmmDestNetworkRecord:
+            {
+            delete iNetworkRecord;
+            iNetworkRecord = static_cast<CommsDat::CCDNetworkRecord*>( aRecordPointer );
+            iNetworkRecordStatus = ECmmRecordStatusLoaded;
+            }
+            break;
+        case ECmmDestApRecord:
+            {
+            delete iDestApRecord;
+            iDestApRecord = static_cast<CommsDat::CCDAccessPointRecord*>( aRecordPointer );
+            iDestApRecordStatus = ECmmRecordStatusLoaded;
+            }
+            break;
+        case ECmmDestMetadataRecord:
+            {
+            delete iMetadataRecord;
+            iMetadataRecord = static_cast<CCDSNAPMetadataRecord*>( aRecordPointer );
+            iMetadataRecordStatus = ECmmRecordStatusLoaded;
+            }
+            break;
+        default:
+            {
+            ret = KErrNotFound;
+            }
+            break;
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETRECORDPOINTER_EXIT );
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// Gets a reference to the requested record pointer.
+// ---------------------------------------------------------------------------
+//
+TInt CCmmDestinationInstance::GetRecordPointer(
+        const TCmmDbRecords& aDestRecord,
+        CommsDat::CCDRecordBase*& aRecordPointer )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETRECORDPOINTER_ENTRY );
+
+    TInt ret( KErrNone );
+    aRecordPointer = NULL;
+    switch ( aDestRecord )
+        {
+        case ECmmDestNetworkRecord:
+            {
+            aRecordPointer = static_cast<CommsDat::CCDRecordBase*>( iNetworkRecord );
+            }
+            break;
+        case ECmmDestApRecord:
+            {
+            aRecordPointer = static_cast<CommsDat::CCDRecordBase*>( iDestApRecord );
+            }
+            break;
+        case ECmmDestMetadataRecord:
+            {
+            aRecordPointer = static_cast<CommsDat::CCDRecordBase*>( iMetadataRecord );
+            }
+            break;
+        default:
+            {
+            ASSERT( 0 );
+            ret = KErrNotFound;
+            }
+            break;
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETRECORDPOINTER_EXIT );
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// Save the contents of this destination into database. All connection methods
+// including embedded destination, that the client has open handles to, are
+// also updated.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::UpdateL()
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_UPDATEL_ENTRY );
+
+    if ( AllMandatoryRecordsContainData() )
+        {
+        // Check for metadata conflicts.
+        if ( ConflictingMetadataFoundL() )
+            {
+            OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_UPDATEL_EXIT );
+
+            User::Leave( KErrAlreadyExists );
+            }
+
+        // Check that the destination name is still valid and not in use already.
+        if ( iCache->DestinationExistsWithNameL( iNetworkRecord->iRecordName.GetL(), iId ) )
+            {
+            OstTraceFunctionExit0( DUP1_CCMMDESTINATIONINSTANCE_UPDATEL_EXIT );
+
+            User::Leave( KErrAlreadyExists );
+            }
+
+        iCache->UpdateDestinationL( *this );
+        }
+    else
+        {
+        User::Leave( KErrCorrupt );
+        }
+
+    OstTraceFunctionExit0( DUP2_CCMMDESTINATIONINSTANCE_UPDATEL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Get the destination name.
+// ---------------------------------------------------------------------------
+//
+TDesC& CCmmDestinationInstance::GetDestinationNameL()
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETDESTINATIONNAMEL_ENTRY );
+
+    RefreshRecordL( ECmmDestNetworkRecord );
+
+    if ( !iNetworkRecord )
+        {
+        OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETDESTINATIONNAMEL_EXIT );
+
+        User::Leave( KErrCorrupt );
+        }
+
+    OstTraceFunctionExit0( DUP1_CCMMDESTINATIONINSTANCE_GETDESTINATIONNAMEL_EXIT );
+    return iNetworkRecord->iRecordName.GetL();
+    }
+
+// ---------------------------------------------------------------------------
+// Get the localised destination name.
+// ---------------------------------------------------------------------------
+//
+HBufC* CCmmDestinationInstance::GetLocalisedDestinationNameL()
+    {
+    RefreshRecordL( ECmmDestNetworkRecord );
+
+    if ( !iNetworkRecord )
+        {
+        User::Leave( KErrCorrupt );
+        }
+
+    TUint32 purpose( 0 );
+    GetMetadataL( CMManager::ESnapMetadataPurpose, purpose );
+    HBufC* resolvedText( NULL );
+    TBool isLocalised( EFalse );
+    switch ( purpose )
+        {
+        case CMManager::ESnapPurposeInternet:
+            {
+            _LIT( KDestinationTextId, "txt_occ_dblist_internet");
+            resolvedText = CCmManagerTextResolver::ResolveTextL( KDestinationTextId );
+            isLocalised = ETrue;
+            }
+            break;
+        case CMManager::ESnapPurposeOperator:
+            {
+            _LIT( KDestinationTextId, "txt_occ_dblist_operator_services");
+            resolvedText = CCmManagerTextResolver::ResolveTextL( KDestinationTextId );
+            isLocalised = ETrue;
+            }
+            break;
+        case CMManager::ESnapPurposeIntranet:
+            {
+            _LIT( KDestinationTextId, "txt_occ_dblist_intranet");
+            resolvedText = CCmManagerTextResolver::ResolveTextL( KDestinationTextId );
+            isLocalised = ETrue;
+            }
+            break;
+        default:
+            break;
+        }
+
+    // Not Internet, operator or intranet...or something went wrong 
+    if ( !isLocalised || ( isLocalised && !resolvedText ) )
+        {
+        resolvedText = ( iNetworkRecord->iRecordName.GetL() ).AllocL();
+        }
+    
+    return resolvedText;
+    }
+
+// ---------------------------------------------------------------------------
+// Set the destination name.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetDestinationNameL( const TDesC& aDestinationName )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETDESTINATIONNAMEL_ENTRY );
+
+    //TODO, capability check depending on destination protection level, or if it is internet destination. Internet destination should be protected always?
+
+    // Write action, load all records.
+    LoadAllRecordsL();
+
+    iNetworkRecord->iRecordName.SetL( aDestinationName );
+    iDestApRecord->iRecordName.SetL( aDestinationName );
+
+    iNetworkRecordStatus = ECmmRecordStatusModified;
+    iDestApRecordStatus = ECmmRecordStatusModified;
+    iStatus = ECmmDestinationStatusChanged;
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETDESTINATIONNAMEL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Get metadata of specified type.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::GetMetadataL(
+        const CMManager::TSnapMetadataField& aMetadataField,
+        TUint32& aMetadata )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETMETADATAL_ENTRY );
+
+    RefreshRecordL( ECmmDestMetadataRecord );
+
+    if ( !iMetadataRecord )
+        {
+        OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETMETADATAL_EXIT );
+
+        User::Leave( KErrCorrupt );
+        }
+
+    switch ( aMetadataField )
+        {
+        case CMManager::ESnapMetadataInternet:
+            aMetadata = ( TUint32 )( iMetadataRecord->iMetadata ) & CMManager::ESnapMetadataInternet;
+            break;
+        case CMManager::ESnapMetadataHighlight:
+            aMetadata = ( TUint32 )( iMetadataRecord->iMetadata ) & CMManager::ESnapMetadataHighlight;
+            break;
+        case CMManager::ESnapMetadataHiddenAgent:
+            aMetadata = ( TUint32 )( iMetadataRecord->iMetadata ) & CMManager::ESnapMetadataHiddenAgent;
+            break;
+        case CMManager::ESnapMetadataDestinationIsLocalised:
+            aMetadata = ( ( TUint32 )( iMetadataRecord->iMetadata ) & CMManager::ESnapMetadataDestinationIsLocalised ) >> 4;
+            break;
+        case CMManager::ESnapMetadataPurpose:
+            aMetadata = ( ( TUint32 )( iMetadataRecord->iMetadata ) & CMManager::ESnapMetadataPurpose ) >> 8;
+            break;
+        default:
+            User::Leave( KErrArgument );
+            break;
+        }
+
+    OstTraceFunctionExit0( DUP1_CCMMDESTINATIONINSTANCE_GETMETADATAL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Set metadata of specified type.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetMetadataL(
+        const CMManager::TSnapMetadataField& aMetadataField,
+        const TUint32& aMetadata )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATAL_ENTRY );
+
+    // Write action, load all records.
+    LoadAllRecordsL();
+
+    switch ( aMetadataField )
+        {
+        case CMManager::ESnapMetadataInternet:
+            SetMetadataInternetL( aMetadata );
+            break;
+        case CMManager::ESnapMetadataHighlight:
+            SetMetadataHighlight( aMetadata );
+            break;
+        case CMManager::ESnapMetadataHiddenAgent:
+            SetMetadataHiddenAgentL( aMetadata );
+            break;
+        case CMManager::ESnapMetadataDestinationIsLocalised:
+            SetMetadataLocalizationL( aMetadata );
+            break;
+        case CMManager::ESnapMetadataPurpose:
+            SetMetadataPurposeL( aMetadata );
+            break;
+        default:
+            User::Leave( KErrArgument );
+            break;
+        }
+
+    iMetadataRecordStatus = ECmmRecordStatusModified;
+    iStatus = ECmmDestinationStatusChanged;
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATAL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Get destination protection level.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::GetProtectionL( CMManager::TProtectionLevel& aProtectionLevel )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_GETPROTECTIONL_ENTRY );
+
+    RefreshRecordL( ECmmDestMetadataRecord );
+
+    if ( !iMetadataRecord )
+        {
+        User::Leave( KErrCorrupt );
+        }
+
+    TUint32 value = ( ( TUint32 )( iMetadataRecord->iMetadata ) & KDestProtectionLevelMask ) >> KBitsToShiftDestProtectionLevel;
+    switch ( value )
+        {
+        case CMManager::EProtLevel0:
+            aProtectionLevel = CMManager::EProtLevel0;
+            break;
+        case CMManager::EProtLevel1:
+            aProtectionLevel = CMManager::EProtLevel1;
+            break;
+        case CMManager::EProtLevel2:
+            aProtectionLevel = CMManager::EProtLevel2;
+            break;
+        case CMManager::EProtLevel3:
+            aProtectionLevel = CMManager::EProtLevel3;
+            break;
+        default:
+            User::Leave( KErrCorrupt );
+            break;
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_GETPROTECTIONL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Set destination protection level.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetProtectionL(
+        CMManager::TProtectionLevel aProtectionLevel )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETPROTECTIONL_ENTRY );
+
+    // Write action, load all records.
+    LoadAllRecordsL();
+
+    //TODO, verify capability check is done (NetworkControl).
+
+    iCurrentProtectionLevel = aProtectionLevel;
+    if ( !iProtectionChanged )
+        {
+        GetProtectionL( iLastProtectionLevel );
+        }
+    if ( aProtectionLevel == iLastProtectionLevel )
+        {
+        iProtectionChanged = EFalse;
+        }
+    else
+        {
+        iProtectionChanged = ETrue;
+        }
+
+    // Read current metadata without protection bits.
+    TUint32 currentMetadata =
+            ( ( TUint32 )( iMetadataRecord->iMetadata ) & ( ~KDestProtectionLevelMask ) );
+    // Add new protection bits.
+    iMetadataRecord->iMetadata =
+            currentMetadata | ( aProtectionLevel << KBitsToShiftDestProtectionLevel );
+
+    iMetadataRecordStatus = ECmmRecordStatusModified;
+    iStatus = ECmmDestinationStatusChanged;
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETPROTECTIONL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Return true if protection level has been changed. 
+// ---------------------------------------------------------------------------
+//
+TBool CCmmDestinationInstance::ProtectionChanged()
+    {
+    return iProtectionChanged;
+    }
+
+// ---------------------------------------------------------------------------
+// Return the previous valid protection level of this connection method
+// instance.
+// ---------------------------------------------------------------------------
+//
+CMManager::TProtectionLevel CCmmDestinationInstance::LastProtectionLevel()
+    {
+    return iLastProtectionLevel;
+    }
+
+// ---------------------------------------------------------------------------
+// Return the protection level currently set into this destination instance.
+// ---------------------------------------------------------------------------
+//
+CMManager::TProtectionLevel CCmmDestinationInstance::CurrentProtectionLevel()
+    {
+    return iCurrentProtectionLevel;
+    }
+
+// ---------------------------------------------------------------------------
+// Adds a connection method into this destination. Returns the index (priority)
+// in the connection method array where the connection method was added.
+// Embedded destinations can not be added with this method, use
+// AddEmbeddedDestinationL() instead.
+// ---------------------------------------------------------------------------
+//
+TInt CCmmDestinationInstance::AddConnMethodL(
+        const CCmmConnMethodInstance& aConnMethodInstance )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_ADDCONNMETHODL_ENTRY );
+
+    TUint32 connMethodId( aConnMethodInstance.GetId() );
+    TUint32 bearerType( aConnMethodInstance.GetBearerType() );
+
+    // Check that the connection method is not an embedded destination.
+    if ( bearerType == KUidEmbeddedDestination )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    // Check that the connection method is not already inside this destination.
+    for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        if ( connMethodId == iConnMethodItemArray[i].iId )
+            {
+            User::Leave( KErrAlreadyExists );
+            }
+        }
+
+    // Remove the connection method from delete list, if found there.
+    for ( TInt i = 0; i < iConnMethodsToBeDeleted.Count(); i++ )
+        {
+        if ( connMethodId == iConnMethodsToBeDeleted[i] )
+            {
+            iConnMethodsToBeDeleted.Remove( i );
+            break;
+            }
+        }
+
+    // Get the priority value of this connection method according to bearer.
+    TUint bearerPriority( 0 );
+    iCache->BearerPriorityFromIapRecordL(
+            ( CommsDat::CCDIAPRecord* )aConnMethodInstance.GetPluginDataInstance()->iGenRecordArray[KIapRecordIndex],
+            bearerPriority );
+    TCmmConnMethodItem item( connMethodId, bearerType, bearerPriority, 0 );
+
+    // Find out the correct position for the connection method inside this
+    // destination.
+    TInt index = iConnMethodItemArray.Count();
+    for ( TInt i = index - 1; i >= 0; i-- )
+        {
+        if ( iConnMethodItemArray[i].iBearerPriority ==
+                CMManager::KDataMobilitySelectionPolicyPriorityWildCard )
+            {
+            index = i;
+            continue;
+            }
+        if ( iConnMethodItemArray[i].iBearerPriority == bearerPriority )
+            {
+            break;
+            }
+        if ( iConnMethodItemArray[i].iBearerPriority > bearerPriority )
+            {
+            index = i;
+            }
+        }
+    // Add the connection method item into this destination at the correct
+    // position (priority).
+    iConnMethodItemArray.InsertL( item, index );
+
+    SetStatus( ECmmDestinationStatusChanged );
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_ADDCONNMETHODL_EXIT );
+    return index;
+    }
+
+// ---------------------------------------------------------------------------
+// Adds an embedded destination into this destination. Returns the index in
+// the connection method array where the connection method was added.
+// ---------------------------------------------------------------------------
+//
+TInt CCmmDestinationInstance::AddEmbeddedDestinationL(
+        const CCmmDestinationInstance& aEmbeddedDestinationInstance )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_ADDEMBEDDEDDESTINATIONL_ENTRY );
+
+    TUint32 embeddedDestinationId( aEmbeddedDestinationInstance.GetId() );
+
+    // Check that not adding itself.
+    if ( embeddedDestinationId == iId )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    // Check that the embedded destination is not already an embedded
+    // destination in this destination.
+    if ( HasEmbeddedWithId( embeddedDestinationId ) )
+        {
+        User::Leave( KErrAlreadyExists );
+        }
+
+    // A destination can not be added into a destination that is itself an
+    // embedded destination.
+    if ( iCache->DestinationIsEmbedded( iId ) )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    // A destination can not be added into a destination that already has an
+    // embedded destination.
+    if ( HasEmbedded() || iCache->DestinationHasEmbedded( iId ) )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    // A destination that already has an embedded destination can not be added
+    // into a destination.
+    if ( aEmbeddedDestinationInstance.HasEmbedded() ||
+            iCache->DestinationHasEmbedded( embeddedDestinationId ) )
+        {
+        User::Leave( KErrNotSupported );
+        }
+
+    // Check session side destination instances for all clients.
+    // - Check that any destination instance does not contain aDestinationId as
+    //   embedded destination.
+    // - Check that any destination instance for aEmbeddedDestinationId does
+    //   not contain an embedded destination.
+    if ( iCmmSession->EmbeddedDestinationConflictsFromAllSessions( iId, embeddedDestinationId ) )
+        {
+        User::Leave( KErrAlreadyExists );
+        }
+
+    // Add the embedded destination at the end of the connection method item array.
+    TInt index = iConnMethodItemArray.Count();
+    TCmmConnMethodItem item(
+            embeddedDestinationId,
+            KUidEmbeddedDestination,
+            CMManager::KDataMobilitySelectionPolicyPriorityWildCard,
+            0 );
+    iConnMethodItemArray.AppendL( item );
+
+    SetStatus( ECmmDestinationStatusChanged );
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_ADDEMBEDDEDDESTINATIONL_EXIT );
+    return index;
+    }
+
+// ---------------------------------------------------------------------------
+// Delete a connection method that belongs to this destination. If the
+// connection method belongs to any other destination, it is only removed from
+// this destination and not deleted. Does not call update.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::DeleteConnMethodFromDestinationL(
+        const CCmmConnMethodInstance& aConnMethodInstance )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_DELETECONNMETHODFROMDESTINATIONL_ENTRY );
+
+    // Check that the connection method is inside this destination.
+    TUint32 connMethodId( aConnMethodInstance.GetId() );
+    TInt index( KErrNotFound );
+    for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        if ( connMethodId == iConnMethodItemArray[i].iId )
+            {
+            index = i;
+            break;
+            }
+        }
+    if ( index < 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    // Check if the connection method removal is blocked by any virtual IAPs.
+    if ( ConnMethodInDestinationButLocked( connMethodId ) )
+        {
+        User::Leave( KErrLocked );
+        }
+
+    // Check if any virtual IAP points to this connection method, thus blocking
+    // the delete.
+    if ( iCache->ConnMethodPointedToByVirtualIap( connMethodId ) )
+        {
+        User::Leave( KErrLocked );
+        }
+
+    // Check that the connection method is not in use by an active connection.
+    if ( iCache->CheckIfCmConnected( connMethodId ) )
+        {
+        User::Leave( KErrInUse );
+        }
+
+    // This will also remove an embedded destination.
+    iConnMethodItemArray.Remove( index );
+    SetStatus( ECmmDestinationStatusChanged );
+
+    // If this connection method is an embedded destination, then removing it
+    // from this destination is enough. The destination is not deleted.
+    if ( aConnMethodInstance.GetBearerType() != KUidEmbeddedDestination )
+        {
+        // Add connection method to delete list only if not referenced from any
+        // other destination (in database or in any destination handles for the
+        // client currently beeing served).
+        if ( !iCache->ConnMethodInOtherDestination( connMethodId, iId ) &&
+                !iCmmSession->ConnMethodInOtherDestination( connMethodId, iId ) )
+            {
+            if ( iConnMethodsToBeDeleted.Find( connMethodId ) == KErrNotFound )
+                {
+                iConnMethodsToBeDeleted.AppendL( connMethodId );
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_DELETECONNMETHODFROMDESTINATIONL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Remove a connection method from this destination. If the second attribute
+// aTestIfConnected is false, the test to check if connection method is in use
+// is skipped. In this case this should have been already tested by the caller.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::RemoveConnMethodFromDestinationL(
+        const CCmmConnMethodInstance& aConnMethodInstance,
+        const TBool& aTestIfConnected )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_REMOVECONNMETHODFROMDESTINATIONL_ENTRY );
+
+    // Check that the connection method is inside this destination.
+    TUint32 connMethodId( aConnMethodInstance.GetId() );
+    TInt index( KErrNotFound );
+    for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        if ( connMethodId == iConnMethodItemArray[i].iId )
+            {
+            index = i;
+            break;
+            }
+        }
+    if ( index < 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    // Check if the connection method removal is blocked by any virtual IAPs.
+    if ( ConnMethodInDestinationButLocked( connMethodId ) )
+        {
+        User::Leave( KErrLocked );
+        }
+
+    if ( aTestIfConnected )
+        {
+        // Check that the connection method is not in use by an active connection.
+        if ( iCache->CheckIfCmConnected( connMethodId ) )
+            {
+            User::Leave( KErrInUse );
+            }
+        }
+
+    // This will also remove an embedded destination.
+    iConnMethodItemArray.Remove( index );
+    SetStatus( ECmmDestinationStatusChanged );
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_REMOVECONNMETHODFROMDESTINATIONL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Modifies the priority of a connection method inside this destination.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::ModifyConnMethodPriorityL(
+        const CCmmConnMethodInstance& aConnMethodInstance,
+        TUint aIndex )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_MODIFYCONNMETHODPRIORITYL_ENTRY );
+
+    // Check if the connection method is in this destination. Also store the
+    // current index of the connection method.
+    TInt oldIndex( KErrNotFound );
+    for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        if ( iConnMethodItemArray[i].iId == aConnMethodInstance.GetId() )
+            {
+            oldIndex = i;
+            break;
+            }
+        }
+    if ( oldIndex < 0 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    // If connection method is an embedded destination, just return silently.
+    if ( aConnMethodInstance.GetBearerType() == KUidEmbeddedDestination )
+        {
+        OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_MODIFYCONNMETHODPRIORITYL_EXIT );
+        return;
+        }
+
+    //TODO, if CM is virtual IAP that points into DESTINATION, just return silently.
+    //
+    //
+
+    // Check index range.
+    if ( aIndex >= iConnMethodItemArray.Count() )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    // If the given index points to any wildcard priority connection method,
+    // adjust it so it points to the last priority position.
+    TUint numberOfConnMethodsWithPriority( NumberOfConnMethodsWithPriority() );
+    if ( aIndex >= numberOfConnMethodsWithPriority )
+        {
+        if ( numberOfConnMethodsWithPriority == 0 )
+            {
+            // Can't be 0, since aConnMethodInstance is not a wildcard IAP and
+            // is in the array.
+            ASSERT( 0 );
+            User::Leave( KErrCorrupt );
+            }
+        aIndex = numberOfConnMethodsWithPriority--;
+        }
+
+    // Check if the priority is changing from current.
+    if ( oldIndex == aIndex )
+        {
+        OstTraceFunctionExit0( DUP1_CCMMDESTINATIONINSTANCE_MODIFYCONNMETHODPRIORITYL_EXIT );
+        return;
+        }
+
+    // Change the location of the connection method to reflect the new priority.
+    TCmmConnMethodItem item = iConnMethodItemArray[oldIndex];
+    iConnMethodItemArray.Remove( oldIndex );
+    iConnMethodItemArray.InsertL( item, ( TInt )aIndex );
+
+    SetStatus( ECmmDestinationStatusChanged );
+
+    OstTraceFunctionExit0( DUP2_CCMMDESTINATIONINSTANCE_MODIFYCONNMETHODPRIORITYL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Finds a connection method instance that belongs to the same session and
+// matches the provided ID. Return NULL if no match is found.
+// ---------------------------------------------------------------------------
+//
+CCmmConnMethodInstance* CCmmDestinationInstance::FindConnMethodInstanceFromSessionById(
+        const TUint32& aConnMethodId ) const
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_FINDCONNMETHODINSTANCEFROMSESSIONBYID_ENTRY );
+
+    CCmmConnMethodInstance* connMethodInstance = iCmmSession->
+            FindConnMethodInstanceById( aConnMethodId );
+
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_FINDCONNMETHODINSTANCEFROMSESSIONBYID_EXIT );
+    return connMethodInstance;
+    }
+
+// ---------------------------------------------------------------------------
+// Finds a destination instance that belongs to the same session and matches
+// the provided ID. Return NULL if no match is found.
+// ---------------------------------------------------------------------------
+//
+CCmmDestinationInstance* CCmmDestinationInstance::FindDestinationInstanceFromSessionById(
+        const TUint32& aDestinationId ) const
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_FINDDESTINATIONINSTANCEFROMSESSIONBYID_ENTRY );
+
+    CCmmDestinationInstance* destInstance =
+            iCmmSession->FindDestinationInstanceById( aDestinationId );
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_FINDDESTINATIONINSTANCEFROMSESSIONBYID_EXIT );
+    return destInstance;
+    }
+
+// ---------------------------------------------------------------------------
+// Check from all open destination handles in the same session if the given
+// connection method is inside any of them. The given destination is skipped.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmDestinationInstance::ConnMethodInOtherDestinationInSession(
+        const TUint32& aConnMethodId,
+        const TUint32& aDestinationId ) const
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_CONNMETHODINOTHERDESTINATIONINSESSION_ENTRY );
+
+    TBool inOtherSession = iCmmSession->
+            ConnMethodInOtherDestination( aConnMethodId, aDestinationId );
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_CONNMETHODINOTHERDESTINATIONINSESSION_EXIT );
+    return inOtherSession;
+    }
+
+// ---------------------------------------------------------------------------
+// Check if the given connection method is in this destination. Include
+// embedded destinations.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmDestinationInstance::ValidConnMethodIdInDestinationIncludeEmbedded( const TUint32& aConnMethodId ) const
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_VALIDCONNMETHODIDINDESTINATIONINCLUDEEMBEDDED_ENTRY );
+
+    TBool validity( EFalse );
+    if ( aConnMethodId > 0 )
+        {
+        for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+            {
+            if ( iConnMethodItemArray[i].iId == aConnMethodId )
+                {
+                validity = ETrue;
+                break;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_VALIDCONNMETHODIDINDESTINATIONINCLUDEEMBEDDED_EXIT );
+    return validity;
+    }
+
+// ---------------------------------------------------------------------------
+// Check if the given connection method is inside this destination and if it
+// is in a 'locked' status. A locked connection method can't be deleted nor
+// removed from the destination. A connection method becomes locked if it is
+// the only remaining connection method in a destination and a virtual IAP
+// points into that destination.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmDestinationInstance::ConnMethodInDestinationButLocked(
+        const TUint32& aConnMethodId ) const
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_CONNMETHODINDESTINATIONBUTLOCKED_ENTRY );
+
+    TBool result( EFalse );
+    if ( iConnMethodItemArray.Count() == 1 )
+        {
+        if ( iConnMethodItemArray[0].iId == aConnMethodId )
+            {
+            if ( iCache->DestinationPointedToByVirtualIap( iId ) )
+                {
+                result = ETrue;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_CONNMETHODINDESTINATIONBUTLOCKED_EXIT );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Counts how many connection methods that require priority information are
+// currently in this destination. This excludes any virtual IAPs that point to
+// a destination or any embedded destinations from the count. Assumes the
+// connection method array is in order so all wildcard priority IAPs are at the
+// end of the list.
+// ---------------------------------------------------------------------------
+//
+TUint CCmmDestinationInstance::NumberOfConnMethodsWithPriority() const
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_NUMBEROFCONNMETHODSWITHPRIORITY_ENTRY );
+
+    TUint count( iConnMethodItemArray.Count() );
+
+    for ( TUint i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        //TODO, add virtual IAP pointing to SNAP check.
+        if ( iConnMethodItemArray[i].iBearerType == KUidEmbeddedDestination )
+            {
+            count = i;
+            break;
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_NUMBEROFCONNMETHODSWITHPRIORITY_EXIT );
+    return count;
+    }
+
+// ---------------------------------------------------------------------------
+// Check if this destination has an embedded destination. Checks the current
+// (possibly unsaved) status of this destination handle, not the current status
+// in database.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmDestinationInstance::HasEmbedded() const
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_HASEMBEDDED_ENTRY );
+
+    TBool result( EFalse );
+
+    // If there is an embedded destination, it will be at the very last
+    // position in the connection method item array.
+    TInt index = iConnMethodItemArray.Count() - 1;
+    if ( index >= 0 )
+        {
+        if ( iConnMethodItemArray[index].iBearerType == KUidEmbeddedDestination )
+            {
+            result = ETrue;
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_HASEMBEDDED_EXIT );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Check if this destination has an embedded destination with the specified ID.
+// Checks the current (possibly unsaved) status of this destination handle, not
+// the current status in database.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmDestinationInstance::HasEmbeddedWithId( const TUint32& aDestinationId ) const
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_HASEMBEDDEDWITHID_ENTRY );
+
+    TBool result( EFalse );
+
+    // If there is an embedded destination, it will be at the very last
+    // position in the connection method item array.
+    TInt index = iConnMethodItemArray.Count() - 1;
+    if ( index >= 0 )
+        {
+        // No need to check bearer, since ID will not match anyway if the last
+        // item is not an embedded destination.
+        if ( iConnMethodItemArray[index].iId == aDestinationId )
+            {
+            result = ETrue;
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_HASEMBEDDEDWITHID_EXIT );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// After update/delete to database, refresh temporary ID to real ID if
+// necessary and refresh status information for any related handles for
+// all client sessions.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::RefreshHandlesForAllSessions( const TCmmIdStruct& aIdStruct )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_REFRESHHANDLESFORALLSESSIONS_ENTRY );
+
+    iCmmSession->RefreshHandlesForAllSessions( aIdStruct );
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_REFRESHHANDLESFORALLSESSIONS_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// If the destination contains a connection method with matching temporary ID,
+// updates the ID to real ID. This is done after the connection method has been
+// successfully saved into the database.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::RefreshConnMethodId( const TCmmIdStruct& aIdStruct )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_REFRESHCONNMETHODID_ENTRY );
+
+    for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        if ( iConnMethodItemArray[i].iId == aIdStruct.iTemporaryId )
+            {
+            iConnMethodItemArray[i].iId = aIdStruct.iRealId;
+            break;
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_REFRESHCONNMETHODID_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Called after this destination has been updated and database transaction has
+// completed successfully. Sets the internal state of this destination instance
+// to reflect the new valid state.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::UpdateSuccessful()
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_UPDATESUCCESSFUL_ENTRY );
+
+    SetStatus( ECmmDestinationStatusValid );
+    SetStatusForAllRecords( ECmmRecordStatusLoaded );
+    iConnMethodsToBeDeleted.Reset();
+    iProtectionChanged = EFalse;
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_UPDATESUCCESSFUL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Checks if all mandatory records contain data and are ready to be saved into
+// database.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmDestinationInstance::AllMandatoryRecordsContainData() const
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_ALLMANDATORYRECORDSCONTAINDATA_ENTRY );
+
+    TBool result( ETrue );
+
+    if ( iNetworkRecordStatus != ECmmRecordStatusLoaded &&
+            iNetworkRecordStatus != ECmmRecordStatusExpired &&
+            iNetworkRecordStatus != ECmmRecordStatusModified )
+        {
+        result = EFalse;
+        }
+    if ( iDestApRecordStatus != ECmmRecordStatusLoaded &&
+            iDestApRecordStatus != ECmmRecordStatusExpired &&
+            iDestApRecordStatus != ECmmRecordStatusModified )
+        {
+        result = EFalse;
+        }
+    if ( iMetadataRecordStatus != ECmmRecordStatusLoaded &&
+            iMetadataRecordStatus != ECmmRecordStatusExpired &&
+            iMetadataRecordStatus != ECmmRecordStatusModified )
+        {
+        result = EFalse;
+        }
+    if ( !iNetworkRecord || !iDestApRecord || !iMetadataRecord )
+        {
+        result = EFalse;
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_ALLMANDATORYRECORDSCONTAINDATA_EXIT );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Loads a certain type of record from database if it is not up-to-date.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::RefreshRecordL( TCmmDbRecords aRecordType )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_REFRESHRECORDL_ENTRY );
+
+    TCmmRecordStatus status( ECmmRecordStatusBlank );
+    switch ( aRecordType )
+        {
+        case ECmmDestNetworkRecord:
+            status = iNetworkRecordStatus;
+            break;
+        case ECmmDestApRecord:
+            status = iDestApRecordStatus;
+            break;
+        case ECmmDestMetadataRecord:
+            status = iMetadataRecordStatus;
+            break;
+        default:
+            User::Leave( KErrCorrupt ); // Error, unknown type.
+            break;
+        }
+
+    switch ( status )
+        {
+        // Fallthrough intended
+        case ECmmRecordStatusBlank:
+        case ECmmRecordStatusExpired:
+            iCache->LoadDestinationRecordL( *this, aRecordType );
+            break;
+        case ECmmRecordStatusLoaded:
+        case ECmmRecordStatusModified:
+            // Record is up-to-date.
+            break;
+        case ECmmRecordStatusUnsaved:
+        default:
+            User::Leave( KErrCorrupt ); // Error, unknown status.
+            break;
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_REFRESHRECORDL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Loads all records from database that are not up-to-date.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::LoadAllRecordsL()
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_LOADALLRECORDSL_ENTRY );
+
+    RefreshRecordL( ECmmDestNetworkRecord );
+    RefreshRecordL( ECmmDestApRecord );
+    RefreshRecordL( ECmmDestMetadataRecord );
+
+    if ( !iNetworkRecord || !iDestApRecord || !iMetadataRecord )
+        {
+        User::Leave( KErrCorrupt );
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_LOADALLRECORDSL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Set metadata of type ESnapMetadataInternet.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetMetadataInternetL( const TUint32& aMetadata )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATAINTERNETL_ENTRY );
+
+    if ( aMetadata )
+        {
+        if ( iCache->DestinationExistsWithMetadataLocalizedL( *this, CMManager::ELocalisedDestInternet ) )
+            {
+            User::Leave( KErrAlreadyExists );
+            }
+        // Clear ESnapMetadataHiddenAgent-bit.
+        TUint32 value = iMetadataRecord->iMetadata & ( ~CMManager::ESnapMetadataHiddenAgent );
+
+        // Set old ESnapMetadataInternet-bit.
+        value = value | CMManager::ESnapMetadataInternet;
+
+        // Clear ESnapMetadataDestinationIsLocalised-bits.
+        value = value & ( ~CMManager::ESnapMetadataDestinationIsLocalised );
+        // Set ELocalisedDestInternet-value.
+        iMetadataRecord->iMetadata = value | ( CMManager::ELocalisedDestInternet << 4 );
+        value = value | ( CMManager::ELocalisedDestInternet << 4 );
+
+        // Clear ESnapMetadataPurpose-bits.
+        value = value & ( ~CMManager::ESnapMetadataPurpose );
+        // Set ESnapPurposeInternet-value.
+        iMetadataRecord->iMetadata = value | ( CMManager::ESnapPurposeInternet << 8 );
+        }
+    else
+        {
+        // Clear old ESnapMetadataInternet-bit, ESnapMetadataDestinationIsLocalised-bits and CMManager::ESnapMetadataPurpose-bits.
+        TUint32 temp = ~( CMManager::ESnapMetadataInternet | CMManager::ESnapMetadataDestinationIsLocalised | CMManager::ESnapMetadataPurpose );
+        iMetadataRecord->iMetadata = iMetadataRecord->iMetadata & temp;
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATAINTERNETL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Set metadata of type ESnapMetadataHighlight.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetMetadataHighlight( const TUint32& aMetadata )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATAHIGHLIGHTL_ENTRY );
+
+    // TODO: Old CmManager does not perform any duplicate checks when setting highlight.
+    // Now with single click this is not used anymore anyway. So I suggest we don't add any checks here.
+    if ( aMetadata )
+        {
+        // Set ESnapMetadataHighlight-bit.
+        iMetadataRecord->iMetadata = iMetadataRecord->iMetadata | CMManager::ESnapMetadataHighlight;
+        }
+    else
+        {
+        // Clear ESnapMetadataHighlight-bit.
+        iMetadataRecord->iMetadata = iMetadataRecord->iMetadata & ( ~CMManager::ESnapMetadataHighlight );
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATAHIGHLIGHTL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Set metadata of type ESnapMetadataHiddenAgent.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetMetadataHiddenAgentL( const TUint32& aMetadata )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATAHIDDENAGENTL_ENTRY );
+
+    if ( aMetadata )
+        {
+        TUint32 metadataInternet(    iMetadataRecord->iMetadata & CMManager::ESnapMetadataInternet                      );
+        TUint32 metadataLocalized( ( iMetadataRecord->iMetadata & CMManager::ESnapMetadataDestinationIsLocalised ) >> 4 );
+        TUint32 metadataPurpose(   ( iMetadataRecord->iMetadata & CMManager::ESnapMetadataPurpose                ) >> 8 );
+        if ( metadataInternet ||
+                ( metadataLocalized == CMManager::ELocalisedDestInternet ) ||
+                ( metadataPurpose == CMManager::ESnapPurposeInternet ) )
+            {
+            // Not allowed to set ESnapMetadataHiddenAgent if destination is localized or has purpose set.
+            User::Leave( KErrArgument );
+            }
+        // Set ESnapMetadataHiddenAgent-bit.
+        iMetadataRecord->iMetadata = iMetadataRecord->iMetadata | CMManager::ESnapMetadataHiddenAgent;
+        }
+    else
+        {
+        // Clear ESnapMetadataHiddenAgent-bit.
+        iMetadataRecord->iMetadata = iMetadataRecord->iMetadata & ( ~CMManager::ESnapMetadataHiddenAgent );
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATAHIDDENAGENTL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Set metadata of type ESnapMetadataDestinationIsLocalised.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetMetadataLocalizationL( const TUint32& aMetadata )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATALOCALIZATIONL_ENTRY );
+
+    // Check that aMetadata is within valid range.
+    if ( aMetadata > CMManager::ELocalisedDestIntranet )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    TUint32 temp = ~( CMManager::ESnapMetadataInternet | CMManager::ESnapMetadataDestinationIsLocalised | CMManager::ESnapMetadataPurpose );
+    if ( aMetadata == CMManager::ENotLocalisedDest )
+        {
+        // Clear old ESnapMetadataInternet-bit, ESnapMetadataDestinationIsLocalised-bits and ESnapMetadataPurpose-bits.
+        iMetadataRecord->iMetadata = iMetadataRecord->iMetadata & temp;
+        }
+    else
+        {
+        if ( iCache->DestinationExistsWithMetadataLocalizedL( *this, aMetadata ) )
+            {
+            User::Leave( KErrAlreadyExists );
+            }
+
+        // Clear old ESnapMetadataInternet-bit, ESnapMetadataDestinationIsLocalised-bits and ESnapMetadataPurpose-bits.
+        TUint32 value = iMetadataRecord->iMetadata & temp;
+        switch ( aMetadata )
+            {
+            case CMManager::ELocalisedDestInternet:
+                {
+                // Clear ESnapMetadataHiddenAgent-bit.
+                value = value & ( ~CMManager::ESnapMetadataHiddenAgent );
+                // Set old ESnapMetadataInternet-bit.
+                value = value | CMManager::ESnapMetadataInternet;
+                // Set ESnapPurposeInternet-value.
+                value = value | ( CMManager::ESnapPurposeInternet << 8 );
+                }
+                break;
+            case CMManager::ELocalisedDestWap:
+                {
+                // Set ESnapPurposeOperator-value.
+                value = value | ( CMManager::ESnapPurposeOperator << 8 );
+                }
+                break;
+            case CMManager::ELocalisedDestMMS:
+                {
+                // Set ESnapMetadataHiddenAgent-bit.
+                value = value | CMManager::ESnapMetadataHiddenAgent;
+                // Set ESnapPurposeMMS-value.
+                value = value | ( CMManager::ESnapPurposeMMS << 8 );
+                }
+                break;
+            case CMManager::ELocalisedDestIntranet:
+                {
+                // Set ESnapPurposeIntranet-value.
+                value = value | ( CMManager::ESnapPurposeIntranet << 8 );
+                }
+                break;
+            default:
+                User::Leave( KErrArgument );
+                break;
+            }
+        // Set ESnapMetadataDestinationIsLocalised-value.
+        iMetadataRecord->iMetadata = value | ( aMetadata << 4 );
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATALOCALIZATIONL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Set metadata of type ESnapMetadataPurpose.
+// ---------------------------------------------------------------------------
+//
+void CCmmDestinationInstance::SetMetadataPurposeL( const TUint32& aMetadata )
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_SETMETADATAPURPOSEL_ENTRY );
+
+    // Check that aMetadata is within valid range.
+    if ( aMetadata > CMManager::ESnapPurposeIntranet )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    TUint32 temp = ~( CMManager::ESnapMetadataInternet | CMManager::ESnapMetadataDestinationIsLocalised | CMManager::ESnapMetadataPurpose );
+    if ( aMetadata == CMManager::ESnapPurposeUnknown )
+        {
+        // Clear old ESnapMetadataInternet-bit, ESnapMetadataDestinationIsLocalised-bits and ESnapMetadataPurpose-bits.
+        iMetadataRecord->iMetadata = iMetadataRecord->iMetadata & temp;
+        }
+    else
+        {
+        if ( iCache->DestinationExistsWithMetadataPurposeL( *this, aMetadata ) )
+            {
+            User::Leave( KErrAlreadyExists );
+            }
+
+        // Clear old ESnapMetadataInternet-bit, ESnapMetadataDestinationIsLocalised-bits and ESnapMetadataPurpose-bits.
+        TUint32 value = iMetadataRecord->iMetadata & temp;
+
+        switch ( aMetadata )
+            {
+            case CMManager::ESnapPurposeInternet:
+                {
+                // Clear ESnapMetadataHiddenAgent-bit.
+                value = value & ( ~CMManager::ESnapMetadataHiddenAgent );
+                // Set old ESnapMetadataInternet-bit.
+                value = value | CMManager::ESnapMetadataInternet;
+                // Set ELocalisedDestInternet-value.
+                value = value | ( CMManager::ELocalisedDestInternet << 4 );
+                }
+                break;
+            case CMManager::ESnapPurposeOperator:
+                {
+                // Set ELocalisedDestWap-value.
+                value = value | ( CMManager::ELocalisedDestWap << 4 );
+                }
+                break;
+            case CMManager::ESnapPurposeMMS:
+                {
+                // Set ESnapMetadataHiddenAgent-bit.
+                value = value | CMManager::ESnapMetadataHiddenAgent;
+                // Set ELocalisedDestMMS-value.
+                value = value | ( CMManager::ELocalisedDestMMS << 4 );
+                }
+                break;
+            case CMManager::ESnapPurposeIntranet:
+                {
+                // Set ELocalisedDestIntranet-value.
+                value = value | ( CMManager::ELocalisedDestIntranet << 4 );
+                }
+                break;
+            default:
+                User::Leave( KErrArgument );
+                break;
+            }
+        // Set ESnapMetadataPurpose-value.
+        iMetadataRecord->iMetadata = value | ( aMetadata << 8 );
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_SETMETADATAPURPOSEL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Checks the current metadata for this destination, and verifies there is no
+// other conflicting destinations in the database.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmDestinationInstance::ConflictingMetadataFoundL()
+    {
+    OstTraceFunctionEntry0( CCMMDESTINATIONINSTANCE_CONFLICTINGMETADATAFOUNDL_ENTRY );
+
+    TBool result( EFalse );
+    TUint32 metadataInternet(    iMetadataRecord->iMetadata & CMManager::ESnapMetadataInternet                      );
+    TUint32 metadataLocalized( ( iMetadataRecord->iMetadata & CMManager::ESnapMetadataDestinationIsLocalised ) >> 4 );
+    TUint32 metadataPurpose(   ( iMetadataRecord->iMetadata & CMManager::ESnapMetadataPurpose                ) >> 8 );
+
+    if ( metadataPurpose )
+        {
+        // Some metadata is set, need to check conflicts in database.
+        switch ( metadataPurpose )
+            {
+            // Fallthrough intended.
+            case CMManager::ESnapPurposeInternet:
+            case CMManager::ESnapPurposeOperator:
+            case CMManager::ESnapPurposeMMS:
+            case CMManager::ESnapPurposeIntranet:
+                result = iCache->DestinationExistsWithMetadataPurposeL( *this, metadataPurpose );
+                break;
+            default:
+                User::Leave( KErrCorrupt ); // Invalid metadata.
+                break;
+            }
+        }
+    else if ( metadataLocalized )
+        {
+        // Error, metadataPurpose was not set. Continue anyway.
+        switch ( metadataLocalized )
+            {
+            // Fallthrough intended.
+            case CMManager::ELocalisedDestInternet:
+            case CMManager::ELocalisedDestWap:
+            case CMManager::ELocalisedDestMMS:
+            case CMManager::ELocalisedDestIntranet:
+                result = iCache->DestinationExistsWithMetadataLocalizedL( *this, metadataLocalized );
+                break;
+            default:
+                User::Leave( KErrCorrupt ); // Invalid metadata.
+                break;
+            }
+        }
+    else if ( metadataInternet )
+        {
+        // Error, metadataPurpose and metadataLocalized was not set. Continue anyway.
+        result = iCache->DestinationExistsWithMetadataLocalizedL( *this, CMManager::ELocalisedDestInternet );
+        }
+
+    OstTraceFunctionExit0( CCMMDESTINATIONINSTANCE_CONFLICTINGMETADATAFOUNDL_EXIT );
+    return result;
+    }
+
+// End of file