cmmanager/cmmgr/cmmserver/src/cmminstancemapping.cpp
branchRCL_3
changeset 24 05bc53fe583b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmmanager/cmmgr/cmmserver/src/cmminstancemapping.cpp	Tue Aug 31 15:35:44 2010 +0300
@@ -0,0 +1,1453 @@
+/*
+* 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:
+* Keeps track of the general destination/connection method structure in
+* database.
+*
+*/
+
+
+#include <metadatabase.h>
+#include <commsdattypesv1_1.h>
+#include <datamobilitycommsdattypes.h>
+#include <cmpluginembdestinationdef.h>
+#include <wlancontainer.h>
+
+#include "cmminstancemapping.h"
+#include "cmpluginbaseeng.h"
+
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "cmminstancemappingTraces.h"
+#endif
+
+
+// ---------------------------------------------------------------------------
+// Two phased construction.
+// ---------------------------------------------------------------------------
+//
+CDestination* CDestination::NewL()
+    {
+    OstTraceFunctionEntry0( CDESTINATION_NEWL_ENTRY );
+
+    CDestination* self = CDestination::NewLC();
+    CleanupStack::Pop( self );
+
+    OstTraceFunctionExit0( CDESTINATION_NEWL_EXIT );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Two phased construction.
+// ---------------------------------------------------------------------------
+//
+CDestination* CDestination::NewLC()
+    {
+    OstTraceFunctionEntry0( CDESTINATION_NEWLC_ENTRY );
+
+    CDestination* self = new( ELeave ) CDestination();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+
+    OstTraceFunctionExit0( CDESTINATION_NEWLC_EXIT );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CDestination::~CDestination()
+    {
+    OstTraceFunctionEntry0( CDESTINATION_CDESTINATION_ENTRY );
+
+    iConnMethodItemArray.Close();
+    iUnsupportedConnMethods.Close();
+
+    OstTraceFunctionExit0( CDESTINATION_CDESTINATION_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Constructor.
+// ---------------------------------------------------------------------------
+//
+CDestination::CDestination()
+    {
+    OstTraceFunctionEntry0( DUP1_CDESTINATION_CDESTINATION_ENTRY );
+
+    iId = 0;
+    iMetadata = 0;
+
+    OstTraceFunctionExit0( DUP1_CDESTINATION_CDESTINATION_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Second phase constructor.
+// ---------------------------------------------------------------------------
+//
+void CDestination::ConstructL()
+    {
+    OstTraceFunctionEntry0( CDESTINATION_CONSTRUCTL_ENTRY );
+    OstTraceFunctionExit0( CDESTINATION_CONSTRUCTL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Two phased construction.
+// ---------------------------------------------------------------------------
+//
+CCmmInstanceMapping* CCmmInstanceMapping::NewL( CCmmCache& aCache )
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_NEWL_ENTRY );
+
+    CCmmInstanceMapping* self = CCmmInstanceMapping::NewLC( aCache );
+    CleanupStack::Pop( self );
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_NEWL_EXIT );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Two phased construction.
+// ---------------------------------------------------------------------------
+//
+CCmmInstanceMapping* CCmmInstanceMapping::NewLC( CCmmCache& aCache )
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_NEWLC_ENTRY );
+
+    CCmmInstanceMapping* self = new( ELeave ) CCmmInstanceMapping( aCache );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_NEWLC_EXIT );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CCmmInstanceMapping::~CCmmInstanceMapping()
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_CCMMINSTANCEMAPPING_ENTRY );
+
+    iConnMethodItemArray.Close();
+    iUnsupportedConnMethods.Close();
+    iDestinations.ResetAndDestroy();
+    iDeletedConnMethods.Close();
+    iDeletedDestinations.Close();
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_CCMMINSTANCEMAPPING_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Constructor.
+// ---------------------------------------------------------------------------
+//
+CCmmInstanceMapping::CCmmInstanceMapping( CCmmCache& aCache ) : iCache( aCache )
+    {
+    OstTraceFunctionEntry0( DUP1_CCMMINSTANCEMAPPING_CCMMINSTANCEMAPPING_ENTRY );
+    iEasyWlanId = 0;
+    OstTraceFunctionExit0( DUP1_CCMMINSTANCEMAPPING_CCMMINSTANCEMAPPING_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Second phase constructor.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::ConstructL()
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_CONSTRUCTL_ENTRY );
+
+    // Read connection methods from database and find the supported ones.
+    ReadAndValidateConnMethodsL();
+    // Read destinations from database.
+    ReadAndValidateDestinationsL();
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_CONSTRUCTL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Resets arrays and reads CMs and Connection Methods
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::RefreshL()
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_REFRESHL_ENTRY );
+
+    ReadAndValidateConnMethodsL();
+    ReadAndValidateDestinationsL();
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_REFRESHL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Check if the given ID is a valid existing destination ID.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmInstanceMapping::ValidDestinationId( const TUint32 aId ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_VALIDDESTINATIONID_ENTRY );
+
+    TBool validity( EFalse );
+
+    if ( aId > 0 )
+        {
+        for ( TInt i = 0; i < iDestinations.Count(); i++ )
+            {
+            if ( iDestinations[i]->iId == aId )
+                {
+                validity = ETrue;
+                break;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_VALIDDESTINATIONID_EXIT );
+    return validity;
+    }
+
+// ---------------------------------------------------------------------------
+// Check if the given ID is a valid existing connection method ID.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmInstanceMapping::ValidConnMethodId( const TUint32 aId ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_VALIDCONNMETHODID_ENTRY );
+
+    TBool validity( EFalse );
+
+    if ( aId > 0 )
+        {
+        for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+            {
+            if ( iConnMethodItemArray[i].iId == aId )
+                {
+                validity = ETrue;
+                break;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_VALIDCONNMETHODID_EXIT );
+    return validity;
+    }
+
+// ---------------------------------------------------------------------------
+// Check if the given ID is a valid existing unsupported connection method ID.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmInstanceMapping::UnsupportedConnMethodId( const TUint32 aId ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_UNSUPPORTEDCONNMETHODID_ENTRY );
+
+    TBool validity( EFalse );
+
+    if ( aId > 0 )
+        {
+        for ( TInt i = 0; i < iUnsupportedConnMethods.Count(); i++ )
+            {
+            if ( iUnsupportedConnMethods[i] == aId )
+                {
+                validity = ETrue;
+                break;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_UNSUPPORTEDCONNMETHODID_EXIT );
+    return validity;
+    }
+
+// ---------------------------------------------------------------------------
+// Check from database if the given destination is an embedded destination in
+// any other destination.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmInstanceMapping::DestinationIsEmbedded( const TUint32 aDestinationId ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_DESTINATIONISEMBEDDED_ENTRY );
+
+    TBool result( EFalse );
+    TInt index( 0 );
+
+    // Iterate through all destinations.
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        // An embedded destination is always at the very last position in
+        // the connection method item array.
+        index = iDestinations[i]->iConnMethodItemArray.Count() - 1;
+        if ( index >= 0 )
+            {
+            // We can skip bearer type check. If the last item isn't an
+            // embedded destination, the ID will not match anyway.
+            if ( iDestinations[i]->iConnMethodItemArray[index].iId == aDestinationId )
+                {
+                result = ETrue;
+                break;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_DESTINATIONISEMBEDDED_EXIT );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Check from database if the given destination has an embedded destination.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmInstanceMapping::DestinationHasEmbedded( const TUint32 aDestinationId ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_DESTINATIONHASEMBEDDED_ENTRY );
+
+    TBool result( EFalse );
+
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        // Find the correct destination.
+        if ( iDestinations[i]->iId == aDestinationId )
+            {
+            // An embedded destination is always at the very last position in
+            // the connection method item array.
+            TInt index = iDestinations[i]->iConnMethodItemArray.Count() - 1;
+            if ( index >= 0 )
+                {
+                if ( iDestinations[i]->iConnMethodItemArray[index].IsEmbedded() )
+                    {
+                    result = ETrue;
+                    }
+                }
+            break;
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_DESTINATIONHASEMBEDDED_EXIT );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Check from database if the given destination is pointed to by any virtual
+// IAP.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmInstanceMapping::DestinationPointedToByVirtualIap(
+        const TUint32 aDestinationId ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_DESTINATIONPOINTEDTOBYVIRTUALIAP_ENTRY );
+
+    TBool result( EFalse );
+    if ( aDestinationId > 0 )
+        {
+        for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+            {
+            if ( iConnMethodItemArray[i].LinkedSnapId() == aDestinationId )
+                {
+                result = ETrue;
+                break;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_DESTINATIONPOINTEDTOBYVIRTUALIAP_EXIT );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Check from database if the given connection method is pointed to by any
+// virtual IAP.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmInstanceMapping::ConnMethodPointedToByVirtualIap(
+        const TUint32 aConnMethodId ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_CONNMETHODPOINTEDTOBYVIRTUALIAP_ENTRY );
+
+    TBool result( EFalse );
+    if ( aConnMethodId > 0 )
+        {
+        for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+            {
+            if ( iConnMethodItemArray[i].LinkedIapId() == aConnMethodId )
+                {
+                result = ETrue;
+                break;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_CONNMETHODPOINTEDTOBYVIRTUALIAP_EXIT );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Check if the given connection method is the only connection method in the
+// given destination and if a virtual IAP points to that destination.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmInstanceMapping::ConnMethodInDestinationButLocked(
+        const TUint32 aConnMethodId,
+        const TUint32 aDestinationId ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_CONNMETHODINDESTINATIONBUTLOCKED_ENTRY );
+
+    TBool result( EFalse );
+
+    // Find destination.
+    CDestination* destination( NULL );
+    destination = GetDestination( aDestinationId );
+
+    if ( destination )
+        {
+        // Check if the destination has only 1 IAP.
+        if ( destination->iConnMethodItemArray.Count() == 1 )
+            {
+            // Check if the IAP has given ID.
+            if ( destination->iConnMethodItemArray[0].iId == aConnMethodId )
+                {
+                // Check if this destination is linked from a virtual IAP.
+                result = DestinationPointedToByVirtualIap( aDestinationId );
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_CONNMETHODINDESTINATIONBUTLOCKED_EXIT );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Get bearer type of connection method matching given ID.
+// Return KErrNone if ID is found, KErrNotFound if not.
+// ---------------------------------------------------------------------------
+//
+TInt CCmmInstanceMapping::GetConnMethodBearerType(
+        const TUint32 aConnMethodId,
+        TUint32& bearerType ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_GETCONNMETHODBEARERTYPE_ENTRY );
+
+    TInt result( KErrNotFound );
+
+    for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        if ( iConnMethodItemArray[i].iId == aConnMethodId )
+            {
+            bearerType = iConnMethodItemArray[i].iBearerType;
+            result = KErrNone;
+            break;
+            }
+        }
+    if ( result == KErrNotFound )
+        {
+        // Embedded destinations are not in connection method array.
+        if ( aConnMethodId > KCmmDestIdIntervalMin && aConnMethodId < KCmmDestIdIntervalMax )
+            {
+            if ( ValidDestinationId( aConnMethodId ) )
+                {
+                bearerType = KUidEmbeddedDestination;
+                result = KErrNone;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_GETCONNMETHODBEARERTYPE_EXIT );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Returns the number of destinations the provided connection method belongs
+// to. Zero is returned if the connection method belongs to no destination
+// (legacy IAP) or does not exist.
+// ---------------------------------------------------------------------------
+//
+TInt CCmmInstanceMapping::DestinationsContainingConnMethod(
+        const TUint32 aConnMethodId ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_CONNMETHODREFERENCECOUNT_ENTRY );
+
+    TInt referenceCount( 0 );
+    TInt count( 0 );
+
+    // Go through each destination.
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        TBool foundInThisDestination( EFalse );
+
+        // Loop through all connection methods in this destination.
+        count = iDestinations[i]->iConnMethodItemArray.Count();
+        for ( TInt j = 0; j < count; j++ )
+            {
+            if ( iDestinations[i]->iConnMethodItemArray[j].iId == aConnMethodId )
+                {
+                foundInThisDestination = ETrue;
+                referenceCount++;
+                break;
+                }
+            }
+
+        // Check unsupported connection methods also.
+        if ( !foundInThisDestination )
+            {
+            count = iDestinations[i]->iUnsupportedConnMethods.Count();
+            for ( TInt j = 0; j < count; j++ )
+                {
+                if ( iDestinations[i]->iUnsupportedConnMethods[j] == aConnMethodId )
+                    {
+                    referenceCount++;
+                    break;
+                    }
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_CONNMETHODREFERENCECOUNT_EXIT );
+    return referenceCount;
+    }
+
+// ---------------------------------------------------------------------------
+// Returns the destination IDs containing the connection method given as
+// parameter.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::DestinationsContainingConnMethodL(
+        const TUint32 aConnMethodId,
+        RArray<TUint32>& aDestinationIds ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_DESTINATIONSCONTAININGCONNMETHODL_ENTRY );
+
+    aDestinationIds.Reset();
+    TInt count( 0 );
+
+    // Go through each destination.
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        TBool foundInThisDestination( EFalse );
+
+        // Loop through all connection methods in this destination.
+        count = iDestinations[i]->iConnMethodItemArray.Count();
+        for ( TInt j = 0; j < count; j++ )
+            {
+            if ( iDestinations[i]->iConnMethodItemArray[j].iId == aConnMethodId )
+                {
+                foundInThisDestination = ETrue;
+                aDestinationIds.AppendL( iDestinations[i]->iId );
+                break;
+                }
+            }
+
+        // Check unsupported connection methods also.
+        if ( !foundInThisDestination )
+            {
+            count = iDestinations[i]->iUnsupportedConnMethods.Count();
+            for ( TInt j = 0; j < count; j++ )
+                {
+                if ( iDestinations[i]->iUnsupportedConnMethods[j] == aConnMethodId )
+                    {
+                    aDestinationIds.AppendL( iDestinations[i]->iId );
+                    break;
+                    }
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_DESTINATIONSCONTAININGCONNMETHODL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Get database session.
+// ---------------------------------------------------------------------------
+//
+CommsDat::CMDBSession& CCmmInstanceMapping::Session() const
+    {
+    // No traces.
+    return iCache.Session();
+    }
+
+// ---------------------------------------------------------------------------
+// Discovers all connection methods from database. Unsupported connection
+// methods are kept separately.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::ReadAndValidateConnMethodsL()
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_READANDVALIDATECONNMETHODSL_ENTRY );
+
+    CMDBRecordSet<CCDIAPRecord>* iapRecordSet =
+            new( ELeave ) CMDBRecordSet<CCDIAPRecord>( KCDTIdIAPRecord );
+    CleanupStack::PushL( iapRecordSet );
+
+    CCDIAPRecord* iapRecord = static_cast<CCDIAPRecord*>(
+            CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
+    CleanupStack::PushL( iapRecord );
+
+    TRAP_IGNORE( iapRecordSet->LoadL( Session() ) );
+
+    // Clear the old info about IAPs.
+    iConnMethodItemArray.Reset();
+    iUnsupportedConnMethods.Reset();
+
+    TInt iapRecordCount( iapRecordSet->iRecords.Count() );
+    TInt err( KErrNone );
+    TUint32 bearerType( 0 );
+    TUint bearerPriority( CMManager::KDataMobilitySelectionPolicyPriorityWildCard );
+
+    for ( TInt i = 0; i < iapRecordCount; i++ )
+        {
+        TUint32 connMethodId( iapRecordSet->iRecords[i]->RecordId() );
+
+        // Check the connection method is not on the deleted list waiting to be
+        // deleted from database.
+        TInt indexInDeletedList = iDeletedConnMethods.FindInOrder( ( TUint )connMethodId );
+        if ( indexInDeletedList == KErrNotFound )
+            {
+            // Check the bearer type of the iap. Leaves if iap is unsupported.
+            iapRecord->SetRecordId( connMethodId );
+            TRAP( err, iCache.BearerInfoFromIapRecordL( iapRecord, bearerType, bearerPriority ) );
+            if ( !err )
+                {
+                TBool isVirtual( EFalse );
+                TUint32 linkedIap( 0 );
+                TUint32 linkedSnap( 0 );
+
+                // BearerInfoFromIapRecordL() has called LoadL() for iapRecord.
+                if( TPtrC( KCDTypeNameVPNService ) == iapRecord->iServiceType )
+                    {
+                    isVirtual = ETrue;
+                    CCDVPNServiceRecord* serviceRecord = static_cast<CCDVPNServiceRecord*>(
+                            CCDRecordBase::RecordFactoryL( KCDTIdVPNServiceRecord ) );
+                    CleanupStack::PushL( serviceRecord );
+                    serviceRecord->SetRecordId( iapRecord->iService );
+                    serviceRecord->LoadL( Session() );
+
+                    // If neither link is set, or both are set, it is an error
+                    // but we ignore it. If both links are set, we use only the
+                    // SNAP link.
+                    if ( !serviceRecord->iServiceSNAP.IsNull() )
+                        {
+                        TUint32 apRecordId = serviceRecord->iServiceSNAP;
+                        if ( apRecordId != 0 )
+                            {
+                            CCDAccessPointRecord* apRecord = static_cast<CCDAccessPointRecord*>(
+                                    CCDRecordBase::RecordFactoryL( KCDTIdAccessPointRecord ) );
+                            apRecord->SetRecordId( apRecordId );
+                            TRAP( err, apRecord->LoadL( Session() ) );
+                            if ( !err )
+                                {
+                                linkedSnap = apRecord->iRecordTag;
+                                }
+                            }
+                        }
+                    if ( !linkedSnap && !serviceRecord->iServiceIAP.IsNull() )
+                        {
+                        linkedIap = serviceRecord->iServiceIAP;
+                        if ( linkedIap >= KCmmConnMethodIdIntervalMax )
+                            {
+                            linkedIap = ( linkedIap & KCDMaskShowRecordId ) >> KBitsInOneByte;
+                            }
+                        }
+
+                    CleanupStack::PopAndDestroy( serviceRecord );
+                    }
+                    TCmmConnMethodItem item(
+                            connMethodId,
+                            bearerType,
+                            bearerPriority,
+                            0,
+                            isVirtual,
+                            linkedIap,
+                            linkedSnap );
+                    iConnMethodItemArray.Append( item ); // Ignore errors.
+                }
+            else if ( err == KErrNotSupported )
+                {
+                iUnsupportedConnMethods.InsertInOrder( ( TUint )connMethodId ); // Ignore errors.
+                }
+            else if ( err == KErrNoMemory )
+                {
+                User::Leave( err );
+                }
+            }
+        }
+
+    CleanupStack::PopAndDestroy( iapRecord );
+    CleanupStack::PopAndDestroy( iapRecordSet );
+
+    // Check all virtual IAPs that link to an IAP. If the link is invalid
+    // (linked IAP not found), the IAP is removed.
+    ValidateVirtualIapsLinkingToIaps();
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_READANDVALIDATECONNMETHODSL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Discovers all destinations and the connection methods inside them.
+// Unsupported connection methods are kept separately.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::ReadAndValidateDestinationsL()
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_READANDVALIDATEDESTINATIONSL_ENTRY );
+
+    // Make 2 loops, first add destinations and then connection methods / embedded destinations.
+    iDestinations.ResetAndDestroy();
+
+    // Explicitly build a TLinearOrder<class>. Used as parameter to RArray::InsertInOrder().
+    TLinearOrder<TCmmConnMethodItem> connMethodItemOrderingLogic( TCmmConnMethodItem::Compare );
+
+    CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>* snapRecordSet =
+            new( ELeave ) CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>(
+                    iCache.TableId( ECmmDbSnapRecord ) );
+    CleanupStack::PushL( snapRecordSet );
+
+    CCDDataMobilitySelectionPolicyRecord* snapRecord =
+            new( ELeave ) CCDDataMobilitySelectionPolicyRecord(
+                    iCache.TableId( ECmmDbSnapRecord ) );
+    CleanupStack::PushL( snapRecord );
+
+    TRAP_IGNORE( snapRecordSet->LoadL( Session() ) );
+
+    // Read snap ID, connection method ID and embedded destination ID.
+    const TInt snapRecordCount( snapRecordSet->iRecords.Count() );
+    for ( TInt i = 0; i < snapRecordCount; i++ )
+        {
+        snapRecord->SetElementId( snapRecordSet->iRecords[i]->ElementId() );
+        snapRecord->LoadL( Session() );
+
+        TUint32 destinationId = (TUint32)( snapRecord->iSNAP );
+        TInt indexInDeletedList = iDeletedDestinations.FindInOrder( ( TUint )destinationId );
+        if ( indexInDeletedList == KErrNotFound )
+            {
+            TUint32 connMethodId = ( snapRecord->iIAP & KCDMaskShowRecordId ) >> 8;
+            TUint32 embeddedDestinationId = (TUint32)( snapRecord->iEmbeddedSNAP );
+
+            // If connMethodId and embeddedDestinationId are 0 this is a destination.
+            if ( connMethodId == 0 && embeddedDestinationId == 0 )
+                {
+                TBool destAlreadyExists = ValidDestinationId( destinationId );
+                if ( !destAlreadyExists )
+                    {
+                    CCDSNAPMetadataRecord* metadataRecord = new( ELeave ) CCDSNAPMetadataRecord(
+                            iCache.TableId( ECmmDestMetadataRecord ) );
+                    CleanupStack::PushL( metadataRecord );
+
+                    // Add destination metadata.
+                    metadataRecord->iSNAP.SetL( destinationId );
+                    if ( metadataRecord->FindL( Session() ) )
+                        {
+                        metadataRecord->LoadL( Session() );
+
+                        CDestination* dest = CDestination::NewLC();
+                        dest->iId = destinationId;
+                        dest->iMetadata = metadataRecord->iMetadata;
+                        iDestinations.AppendL( dest );
+                        CleanupStack::Pop( dest );
+                        }
+                    CleanupStack::PopAndDestroy( metadataRecord );
+                    metadataRecord = NULL;
+                    }
+                }
+            }
+        }
+
+    // Check all virtual IAPs that link to a SNAP. If the link is invalid
+    // (linked SNAP not found), the IAP is removed.
+    ValidateVirtualIapsLinkingToSnaps();
+
+    // Read snap ID, connection method ID and embedded destination ID.
+    for ( TInt i = 0; i < snapRecordCount; i++ )
+        {
+        snapRecord->SetElementId( snapRecordSet->iRecords[i]->ElementId() );
+        snapRecord->LoadL( Session() );
+
+        TUint32 destinationId = (TUint32)( snapRecord->iSNAP );
+        TUint32 connMethodId = ( snapRecord->iIAP & KCDMaskShowRecordId ) >> 8;
+        TUint32 embeddedDestinationId = (TUint32)( snapRecord->iEmbeddedSNAP );
+
+        // If connMethodId or embeddedDestinationId differs from 0 this is a connection method object.
+        if ( connMethodId > 0 || embeddedDestinationId > 0 )
+            {
+            // Find destination.
+            CDestination* destination( NULL );
+            destination = GetDestination( destinationId );
+
+            if ( destination )
+                {
+                if ( connMethodId )
+                    {
+                    // Connection method, not embedded destination.
+                    TBool found( EFalse );
+                    TCmmConnMethodItem item;
+
+                    // Find connection method.
+                    for ( TInt j = 0; j < iConnMethodItemArray.Count(); j++ )
+                        {
+                        if ( iConnMethodItemArray[j].iId == connMethodId )
+                            {
+                            item = iConnMethodItemArray[j];
+                            found = ETrue;
+                            break;
+                            }
+                        }
+                    if ( found )
+                        {
+                        // Make sure no duplicate entries are allowed. Any
+                        // duplicate would imply a corrupted CommsDat.
+                        TInt index = destination->iConnMethodItemArray.Find<TUint32>(
+                                connMethodId,
+                                TCmmConnMethodItem::FindCompare );
+                        if ( index == KErrNotFound )
+                            {
+                            item.iPriority = snapRecord->iPriority;
+                            destination->iConnMethodItemArray.InsertInOrderAllowRepeats(
+                                    item,
+                                    connMethodItemOrderingLogic ); // Ignore errors.
+                            }
+                        }
+                    else
+                        {
+                        // Check if the connection method is unsupported instead.
+                        TBool isUnsupported = UnsupportedConnMethodId( connMethodId );
+                        if ( isUnsupported )
+                            {
+                            destination->iUnsupportedConnMethods.InsertInOrder(
+                                    ( TUint )connMethodId ); // Ignore errors.
+                            }
+                        }
+                    }
+
+                else
+                    {
+                    // Embedded destination, not IAP.
+                    // Prevent destinations from embedding themselves.
+                    if ( embeddedDestinationId != destinationId )
+                        {
+                        // Check embedded destination ID is valid.
+                        TBool valid = ValidDestinationId( embeddedDestinationId );
+                        if ( valid )
+                            {
+                            TCmmConnMethodItem item(
+                                    embeddedDestinationId,
+                                    KUidEmbeddedDestination,
+                                    CMManager::KDataMobilitySelectionPolicyPriorityWildCard,
+                                    CMManager::KDataMobilitySelectionPolicyPriorityWildCard );
+                            destination->iConnMethodItemArray.InsertInOrderAllowRepeats(
+                                    item,
+                                    connMethodItemOrderingLogic );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    CleanupStack::PopAndDestroy( snapRecord );
+    CleanupStack::PopAndDestroy( snapRecordSet );
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_READANDVALIDATEDESTINATIONSL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Goes through the internal IAP table, checking all virtual IAPs that link to
+// an IAP. If the linked IAP is not found, the virtual IAP is removed.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::ValidateVirtualIapsLinkingToIaps()
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_VALIDATEVIRTUALIAPSLINKINGTOIAPS_ENTRY );
+
+    for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        if ( iConnMethodItemArray[i].LinkedIapId() != 0 )
+            {
+            if ( !ValidConnMethodId( iConnMethodItemArray[i].LinkedIapId() ) )
+                {
+                iConnMethodItemArray.Remove( i );
+                i--; // Adjust counter.
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_VALIDATEVIRTUALIAPSLINKINGTOIAPS_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Goes through the internal IAP table, checking all virtual IAPs that link to
+// a SNAP. If the linked SNAP is not found, the virtual IAP is removed.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::ValidateVirtualIapsLinkingToSnaps()
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_VALIDATEVIRTUALIAPSLINKINGTOSNAPS_ENTRY );
+
+    for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        if ( iConnMethodItemArray[i].LinkedSnapId() != 0 )
+            {
+            if ( !ValidDestinationId( iConnMethodItemArray[i].LinkedSnapId() ) )
+                {
+                iConnMethodItemArray.Remove( i );
+                i--; // Adjust counter.
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_VALIDATEVIRTUALIAPSLINKINGTOSNAPS_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Find the destination item matching the provided destination ID.
+// Returns a pointer to the internal destination item, NULL if not found.
+// ---------------------------------------------------------------------------
+//
+CDestination* CCmmInstanceMapping::GetDestination( const TUint32 aDestinationId ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_GETDESTINATION_ENTRY );
+
+    CDestination* destination( NULL );
+    if ( aDestinationId > 0 )
+        {
+        for ( TInt i = 0; i < iDestinations.Count(); i++ )
+            {
+            if ( iDestinations[i]->iId == aDestinationId )
+                {
+                destination = iDestinations[i];
+                break;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_GETDESTINATION_EXIT );
+    return destination;
+    }
+
+// ---------------------------------------------------------------------------
+// Find and return a copy of a connection method item matching the given ID.
+// Returns KErrNotFound, if the connection method is not found.
+// ---------------------------------------------------------------------------
+//
+TInt CCmmInstanceMapping::GetConnMethodItem(
+        const TUint32 aConnMethodId,
+        TCmmConnMethodItem& aConnMethodItem ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_GETCONNMETHODITEM_ENTRY );
+
+    TInt result( KErrNotFound );
+    for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        if ( iConnMethodItemArray[i].iId == aConnMethodId )
+            {
+            aConnMethodItem = iConnMethodItemArray[i];
+            result = KErrNone;
+            break;
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_GETCONNMETHODITEM_EXIT );
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Returns all conenction method IDs. Unsupported connection methods are
+// included if aCheckBearerType is set to EFalse.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::GetAllConnMethodsL(
+        RArray<TUint32>& aConnMethodArray,
+        TBool aCheckBearerType ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_GETCONNMETHODSL_ENTRY );
+
+    TInt connMethodCount = iConnMethodItemArray.Count();
+    aConnMethodArray.Reset();
+
+    if ( aCheckBearerType )
+        {
+        aConnMethodArray.ReserveL( connMethodCount );
+        }
+    else
+        {
+        aConnMethodArray.ReserveL( connMethodCount + iUnsupportedConnMethods.Count() );
+        }
+
+    for ( TInt i = 0; i < connMethodCount; i++ )
+        {
+        aConnMethodArray.AppendL( iConnMethodItemArray[i].iId );
+        }
+    if ( !aCheckBearerType )
+        {
+        // Include unsupported connection methods also.
+        for ( TInt i = 0; i < iUnsupportedConnMethods.Count(); i++ )
+            {
+            aConnMethodArray.AppendL( ( TUint32 )iUnsupportedConnMethods[i] );
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_GETCONNMETHODSL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Return the number of destinations in database.
+// ---------------------------------------------------------------------------
+//
+TInt CCmmInstanceMapping::GetDestinationCount() const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_GETDESTINATIONCOUNT_ENTRY );
+
+    return iDestinations.Count();
+    }
+
+// ---------------------------------------------------------------------------
+// Return an array containing all destination IDs.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::GetDestinationsL( RArray<TUint32>& aDestinationArray ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_GETDESTINATIONSL_ENTRY );
+
+    aDestinationArray.Reset();
+    aDestinationArray.ReserveL( iDestinations.Count() ); // Re-allocates only if more is needed.
+
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        aDestinationArray.AppendL( iDestinations[i]->iId );
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_GETDESTINATIONSL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Inserts all the valid connection methods inside the given destination into
+// the provided connection method item array. The array is reset first.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::GetConnMethodsFromDestinationL(
+        const TUint32 aDestinationId,
+        RArray<TCmmConnMethodItem>& aConnMethodArray ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_GETCONNMETHODSFROMDESTINATIONL_ENTRY );
+
+    TBool destinationFound( EFalse );
+
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        if ( iDestinations[i]->iId == aDestinationId )
+            {
+            destinationFound = ETrue;
+            aConnMethodArray.Reset();
+            aConnMethodArray.ReserveL( iDestinations[i]->iConnMethodItemArray.Count() );
+
+            for ( TInt j = 0; j < iDestinations[i]->iConnMethodItemArray.Count(); j++ )
+                {
+                aConnMethodArray.AppendL( iDestinations[i]->iConnMethodItemArray[j] );
+                }
+            break;
+            }
+        }
+    if ( !destinationFound )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_GETCONNMETHODSFROMDESTINATIONL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Check if the given connection method belongs to any other destination than
+// the one provided.
+// ---------------------------------------------------------------------------
+//
+TBool CCmmInstanceMapping::ConnMethodInOtherDestination(
+        const TUint32 aConnMethodId,
+        const TUint32 aDestinationId )
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_CONNMETHODINOTHERDESTINATION_ENTRY );
+
+    // Loop through all destinations.
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        // Skip the specified destination.
+        if ( iDestinations[i]->iId != aDestinationId )
+            {
+            // Loop through all connection methods in the current destination.
+            for ( TInt j = 0; j < iDestinations[i]->iConnMethodItemArray.Count(); j++ )
+                {
+                if ( iDestinations[i]->iConnMethodItemArray[j].iId == aConnMethodId )
+                    {
+                    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_CONNMETHODINOTHERDESTINATION_EXIT );
+                    return ETrue;
+                    }
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( DUP1_CCMMINSTANCEMAPPING_CONNMETHODINOTHERDESTINATION_EXIT );
+    return EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// Return the EasyWLAN IAP ID, zero if not found or WLAN not supported.
+// ---------------------------------------------------------------------------
+//
+TUint32 CCmmInstanceMapping::EasyWlanIdL()
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_EASYWLANIDL_ENTRY );
+
+    iEasyWlanId = 0;
+
+    // Check WLAN support.
+    if ( iCache.WlanSupported() )
+        {
+        CMDBRecordSet<CCDIAPRecord>* iapRecordSet =
+                new( ELeave ) CMDBRecordSet<CCDIAPRecord>( KCDTIdIAPRecord );
+        CleanupStack::PushL( iapRecordSet );
+        TRAP_IGNORE( iapRecordSet->LoadL( Session() ) );
+
+        TInt iapRecordCount( iapRecordSet->iRecords.Count() );
+        for ( TInt i = 0; i < iapRecordCount; i++ )
+            {
+            CCDIAPRecord* iapRecord = ( CCDIAPRecord* )iapRecordSet->iRecords[i];
+
+            if ( TPtrC( iapRecord->iServiceType ) == TPtrC( KCDTypeNameLANService ) &&
+                    TPtrC( iapRecord->iBearerType ) == TPtrC( KCDTypeNameLANBearer ) )
+                {
+                TUint32 serviceId = iapRecord->iService;
+
+                CCDWlanServiceRecord* wlanServ =
+                        new( ELeave ) CCDWlanServiceRecord(
+                                CCDWlanServiceRecord::TableIdL( Session() ) );
+                CleanupStack::PushL( wlanServ );
+
+                wlanServ->iWlanServiceId.SetL( serviceId );
+                if ( wlanServ->FindL( Session() ) )
+                    {
+                    wlanServ->LoadL( Session() );
+                    // Only EasyWLAN IAP has NULL in SSID field.
+                    if ( wlanServ->iWLanSSID.IsNull() ||
+                            !( TPtrC( wlanServ->iWLanSSID ).Compare( KNullDesC ) ) )
+                        {
+                        iEasyWlanId = iapRecord->RecordId();
+                        }
+                    }
+                CleanupStack::PopAndDestroy( wlanServ );
+                }
+            if ( iEasyWlanId != 0 )
+                {
+                break;
+                }
+            }
+        CleanupStack::PopAndDestroy( iapRecordSet );
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_EASYWLANIDL_EXIT );
+    return iEasyWlanId;
+    }
+
+// ---------------------------------------------------------------------------
+// Find out the internet destination ID. ID is set to 0 if not found.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::InternetDestinationIdL( TUint& aInternetDestinationId )
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_INTERNETDESTINATIONIDL_ENTRY );
+
+    // Set to zero in case the destination is not found.
+    aInternetDestinationId = 0;
+
+    CommsDat::CMDBRecordSet<CCDSNAPMetadataRecord>* metaSet =
+            new( ELeave )CommsDat::CMDBRecordSet<CCDSNAPMetadataRecord>(
+                    iCache.TableId( ECmmDestMetadataRecord ) );
+    CleanupStack::PushL( metaSet );
+
+    TRAP_IGNORE( metaSet->LoadL( Session() ) );
+
+    CCDSNAPMetadataRecord* metadataRecord =
+            new( ELeave ) CCDSNAPMetadataRecord(
+                    iCache.TableId( ECmmDestMetadataRecord ) );
+    CleanupStack::PushL( metadataRecord );
+
+    for ( TInt i = 0; i < metaSet->iRecords.Count(); i++ )
+        {
+        metadataRecord->SetRecordId( metaSet->iRecords[i]->RecordId() );
+        metadataRecord->LoadL( Session() );
+
+        TUint32 metadata = metadataRecord->iMetadata;
+
+        TUint32 internet = metadata &
+                CMManager::ESnapMetadataInternet;
+        TUint32 localizationValue = ( metadata &
+                CMManager::ESnapMetadataDestinationIsLocalised ) >> 4;
+        TUint32 purposeValue = ( metadata &
+                CMManager::ESnapMetadataPurpose ) >> 8;
+
+        // The first record that has a matching value in any of the 3 metadata
+        // fields will be taken as the internet snap.
+        if ( internet ||
+                ( localizationValue == CMManager::ELocalisedDestInternet ) ||
+                ( purposeValue == CMManager::ESnapPurposeInternet ) )
+            {
+            TInt id = metadataRecord->iSNAP;
+            if ( ValidDestinationId( ( TUint32 )id ) )
+                {
+                aInternetDestinationId = ( TUint )id;
+                break;
+                }
+            }
+        }
+    CleanupStack::PopAndDestroy( metadataRecord );
+    CleanupStack::PopAndDestroy( metaSet );
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_INTERNETDESTINATIONIDL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Add a connection method ID to deleted list. Ignores any duplicates. Also
+// removes the connection method from destination/connection method structures
+// so Refresh()-call is not needed. Use this method if the connection method
+// has not been removed from database yet.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::AddConnMethodToDeletedListL( const TUint aConnMethodId )
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_ADDCONNMETHODTODELETEDLISTL_ENTRY );
+
+    iDeletedConnMethods.InsertInOrderL( aConnMethodId );
+
+    // Remove the connection method from current destination/connection method structures.
+    RemoveConnMethod( aConnMethodId );
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_ADDCONNMETHODTODELETEDLISTL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Remove a connection method ID from deleted list. Nothing happens if ID is
+// not found from the list.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::RemoveConnMethodFromDeletedList( const TUint aConnMethodId )
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_REMOVECONNMETHODFROMDELETEDLIST_ENTRY );
+
+    TInt index = iDeletedConnMethods.FindInOrder( aConnMethodId );
+    if ( index != KErrNotFound )
+        {
+        iDeletedConnMethods.Remove( index );
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_REMOVECONNMETHODFROMDELETEDLIST_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Add a destination ID to deleted list. Ignores any duplicates. Also removes
+// the destination from destination/connection method structures so
+// Refresh()-call is not needed. Use this method if the connection method has
+// not been removed from database yet.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::AddDestinationToDeletedListL( const TUint aDestinationId )
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_ADDDESTINATIONTODELETEDLISTL_ENTRY );
+
+    iDeletedDestinations.InsertInOrderL( aDestinationId );
+
+    // Remove the destination from current destination/connection method structures.
+    RemoveDestination( aDestinationId );
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_ADDDESTINATIONTODELETEDLISTL_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Remove a destination ID from deleted list. Nothing happens if ID is not
+// found from the list.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::RemoveDestinationFromDeletedList( const TUint aDestinationId ) //TODO, check removal is called in all necessary places.
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_REMOVEDESTINATIONFROMDELETEDLIST_ENTRY );
+
+    TInt index = iDeletedDestinations.FindInOrder( aDestinationId );
+    if ( index != KErrNotFound )
+        {
+        iDeletedDestinations.Remove( index );
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_REMOVEDESTINATIONFROMDELETEDLIST_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Remove the connection method from current destination/connection method
+// structures. This is a lot faster than calling Refresh(). Use this method if
+// the connection method has been removed from database.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::RemoveConnMethod( const TUint32 aConnMethodId )
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_REMOVECONNMETHOD_ENTRY );
+
+    // Remove from list of connection methods.
+    for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        if ( iConnMethodItemArray[i].iId == aConnMethodId )
+            {
+            iConnMethodItemArray.Remove( i );
+            break;
+            }
+        }
+
+    // Remove connection method from all destinations.
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        for ( TInt j = 0; j < iDestinations[i]->iConnMethodItemArray.Count(); j++ )
+            {
+            if ( iDestinations[i]->iConnMethodItemArray[j].iId == aConnMethodId )
+                {
+                iDestinations[i]->iConnMethodItemArray.Remove( j );
+                break;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_REMOVECONNMETHOD_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Remove the connection method from current destination/connection method
+// structures. This is a lot faster than calling Refresh(). Use this method if
+// the connection method has been removed from database.
+// Also adds the ID of any changed destinations to the provided array.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::RemoveConnMethod(
+        const TUint32 aConnMethodId,
+        RArray<TUint32>& aChangedDestinations )
+    {
+    OstTraceFunctionEntry0( DUP1_CCMMINSTANCEMAPPING_REMOVECONNMETHOD_ENTRY );
+
+    // Remove from list of connection methods.
+    for ( TInt i = 0; i < iConnMethodItemArray.Count(); i++ )
+        {
+        if ( iConnMethodItemArray[i].iId == aConnMethodId )
+            {
+            iConnMethodItemArray.Remove( i );
+            break;
+            }
+        }
+
+    // Remove connection method from all destinations.
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        for ( TInt j = 0; j < iDestinations[i]->iConnMethodItemArray.Count(); j++ )
+            {
+            if ( iDestinations[i]->iConnMethodItemArray[j].iId == aConnMethodId )
+                {
+                iDestinations[i]->iConnMethodItemArray.Remove( j );
+                // Add ID of changed destination into array. Ignore any error.
+                aChangedDestinations.Append( iDestinations[i]->iId );
+                break;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( DUP1_CCMMINSTANCEMAPPING_REMOVECONNMETHOD_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Remove the destination from current destination/connection method
+// structures. This is a lot faster than calling Refresh(). Use this method if
+// the connection method has been removed from database.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::RemoveDestination( const TUint32 aDestinationId )
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_REMOVEDESTINATION_ENTRY );
+
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        if ( iDestinations[i]->iId == aDestinationId )
+            {
+            delete iDestinations[i];
+            iDestinations.Remove( i );
+            i--;
+            }
+        else
+            {
+            // Check also if the destination is an embedded destination
+            // anywhere, and remove that reference too.
+            TInt cmCount( iDestinations[i]->iConnMethodItemArray.Count() );
+            if ( cmCount )
+                {
+                if ( iDestinations[i]->iConnMethodItemArray[cmCount - 1].iId == aDestinationId )
+                    {
+                    iDestinations[i]->iConnMethodItemArray.Remove( cmCount - 1 );
+                    }
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_REMOVEDESTINATION_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Remove the connection method from all destinations in the current
+// destination/connection method structures. This is a lot faster than calling
+// Refresh(). The ID of any changed destination is added to the
+// aChangedDestinations-array.
+// ---------------------------------------------------------------------------
+//
+void CCmmInstanceMapping::RemoveConnMethodFromDestinations(
+        const TUint32 aConnMethodId,
+        RArray<TUint32>& aChangedDestinations )
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_REMOVECONNMETHODFROMDESTINATIONS_ENTRY );
+
+    // Remove given connection method from all destinations.
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        for ( TInt j = 0; j < iDestinations[i]->iConnMethodItemArray.Count(); j++ )
+            {
+            if ( iDestinations[i]->iConnMethodItemArray[j].iId == aConnMethodId )
+                {
+                iDestinations[i]->iConnMethodItemArray.Remove( j );
+                // Add ID of changed destination into array. Ignore any error.
+                aChangedDestinations.Append( iDestinations[i]->iId );
+                break;
+                }
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_REMOVECONNMETHODFROMDESTINATIONS_EXIT );
+    }
+
+// ---------------------------------------------------------------------------
+// Iterate through destinations to find the one identified with provided ID
+// and return its metadata.
+// ---------------------------------------------------------------------------
+//
+TUint32 CCmmInstanceMapping::DestinationMetadata(
+        const TUint32 aDestinationId ) const
+    {
+    OstTraceFunctionEntry0( CCMMINSTANCEMAPPING_DESTINATIONMETADATA_ENTRY );
+
+    TUint32 metadata( 0 );
+    for ( TInt i = 0; i < iDestinations.Count(); i++ )
+        {
+        if ( iDestinations[i]->iId == aDestinationId )
+            {
+            metadata = iDestinations[i]->iMetadata;
+            break;
+            }
+        }
+
+    OstTraceFunctionExit0( CCMMINSTANCEMAPPING_DESTINATIONMETADATA_EXIT );
+    return metadata;
+    }
+
+// End of file