// Copyright (c) 2006-2009 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:
//

/**
 @file
*/
#include "ss_tiermanagerutils.h"

#include <comms-infras/ss_log.h>
#include <comms-infras/ss_metaconnprov.h>
#include <in_sock.h> //KAfInet
#include <es_connpref.h>
#include <commsdattypesv1_1.h> // CommsDat
#include <comms-infras/commsdatschema.h> // CommsDat
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <commsdattypesv1_1_partner.h>
#include <commsdattypesv1_1_internal.h>
#include <es_sock_internal.h>
#endif
#include <commdbconnpref.h> //TCommDbConnPref
#include <comms-infras/ss_thread.h>
#include <comms-infras/esock_params.h> //TConnAPPref
#include <comms-infras/ss_mcprnodemessages.h> //RConnPrefList
#include <agentdialog.h> //TConnectionPrefs
#include <elements/sd_std.h> //RTierThreadMap
#include "ss_tierthreadmap.h"


#ifdef _DEBUG
// Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
// (if it could happen through user error then you should give it an explicit, documented, category + code)
_LIT(KSpecAssert_ESockSSockTrMngU, "ESockSSockTrMngU");
#endif

using namespace ESock;
using namespace CommsDat;
using namespace Den;
using namespace CommsFW;


/**
   TierManagerUtils panic category
*/
_LIT(KTierManagerUtils, "TierManagerUtils");

const TInt KEsockLinkFlag    =  0x80000000;

/** Panics generated by the Comms Channels
*/
enum TTierManagerUtilsPanics
	{
	EInvalidTierId          = 0,
	EInvalidAccessPointId   = 1,
	EInvalidCprId           = 2,
	EInvalidSCprId          = 3,
	EInvalidIapId           = 4,
	EInvalidProtocolId      = 5,
	EInvalidAPSelPolId      = 6
	};

//private, not exported, used with legacy implicit flows only
TUid TierManagerUtils::MapTierIdsForLegacyImplicitFlowsL(TUid aTierId, TUint aProtocol)
	{
	//If necessary, map the KAfInet to a default tier
	TUid mappedTier = MapTierIdsL(aTierId, aProtocol);

	//Now find the tier ID.
	CMDBSession* dbs = CMDBSession::NewLC(KCDVersion1_2);
	CCDTierRecord* tierRec = NULL;
	TRAP_IGNORE(tierRec = TierManagerUtils::LoadTierRecordL(mappedTier, *dbs));
	if(tierRec==NULL)
		{
		if(aTierId.iUid != KAfInet)
			{
			// In the absence of a trier record for this address family try using the KAfInet one
			// This covers the case of legacy protocols such as SMS which only need the top tier
			// The protocol argument is irrelevent for this.
			mappedTier = TierManagerUtils::MapTierIdsL(TUid::Uid(KAfInet), 0);
			tierRec = TierManagerUtils::LoadTierRecordL(mappedTier, *dbs);
			}
		else
			{
			User::Leave(KErrNotFound);
			}
		}

	delete tierRec;
	CleanupStack::PopAndDestroy(dbs);
	return mappedTier;
	}

//only called from functions which are returning AP fields.
TInt TierManagerUtils::ResolveDefAPtoTagL(TInt aElementId, CommsDat::CMDBSession& aDbs )
    {
    CMDBField<TInt>* iRecordTag = new (ELeave) CMDBField<TInt>(aElementId | KCDTIdRecordTag);
    CleanupStack::PushL(iRecordTag);

    iRecordTag->LoadL(aDbs);

	TInt temp = *iRecordTag;
	CleanupStack::PopAndDestroy(iRecordTag);
	return temp;
    }

//Here we have an AccessPoint record Id. Based on that the TagId of the record
//should be given back...
EXPORT_C TInt TierManagerUtils::ConvertSNAPPrefToTagIdL(TUint aSNAPPref, CommsDat::CMDBSession& aDbs)
	{
    CMDBField<TInt>* apTag = new (ELeave) CMDBField<TInt>(KCDTIdAccessPointRecord | KCDTIdRecordTag);
    CleanupStack::PushL(apTag);
    apTag->SetRecordId(aSNAPPref);

    apTag->LoadL(aDbs);

	TInt temp = *apTag;
	CleanupStack::PopAndDestroy(apTag);
	return temp;
	}

EXPORT_C TUid TierManagerUtils::MapElementIdToTagId(TUint aElementId, CommsDat::CMDBSession& aDbs)
    {
    CMDBField<TInt>* recordTag = new (ELeave) CMDBField<TInt>((aElementId & KCDMaskShowRecordType) |
                                                              (aElementId & KCDMaskShowRecordId) |
                                                              KCDTIdRecordTag);
    CleanupStack::PushL(recordTag);

    recordTag->LoadL(aDbs);

	TUid temp;
	temp.iUid = *recordTag;

	CleanupStack::PopAndDestroy(recordTag);

	return temp;
    }

//
//CTierManagerUtils - for commsdat manipulation
EXPORT_C TUid TierManagerUtils::MapTierIdsL(TUid aTierId, TUint /*aProtocol*/)
	{
	// Defined here to avoid a dependency on SIP headers(sipconnpref.h)
	const TUint KAFSip = 0x10000;
	const TUint KAFSipTierMgrFactoryImplementionUid = 0x200041F7;

	//Maps legacy or other thier ids (like the old address family) to new tier ids.
	switch (aTierId.iUid)
		{
		case KAFSip:
				return TUid::Uid(KAFSipTierMgrFactoryImplementionUid);
		}

	return aTierId;
	}


EXPORT_C CCDTierRecord* TierManagerUtils::LoadTierRecordL(TUid aTierId, CMDBSession& aDbs)
	{
	__ASSERT_ALWAYS(aTierId.iUid>0,User::Panic(KTierManagerUtils,EInvalidTierId));

    CCDTierRecord* tierRec = static_cast<CCDTierRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdTierRecord));
    CleanupStack::PushL(tierRec);
    tierRec->iRecordTag = aTierId.iUid;

	TBool found = tierRec->FindL(aDbs);

	if (!found)
    	{
    	User::Leave(KErrNotFound);
    	}
    if (static_cast<TInt>(tierRec->iDefaultAccessPoint)!=0)
        {
        TInt defTierElemId = ResolveDefAPtoTagL(static_cast<TInt>(tierRec->iDefaultAccessPoint), aDbs );
        tierRec->iDefaultAccessPoint = defTierElemId;
        }

	__ASSERT_DEBUG(tierRec->iTierManagerName.TypeId() == KCDTIdTierManagerName, User::Panic(KSpecAssert_ESockSSockTrMngU, 1)); // Panics if built against incorrect CommsDat.
	CleanupStack::Pop(tierRec);
	return tierRec;
	}


EXPORT_C CCDTierRecord* TierManagerUtils::LoadTierRecordL(CommsDat::TMDBElementId aTierId, CommsDat::CMDBSession& aDbs)
	{
	__ASSERT_ALWAYS(aTierId>0,User::Panic(KTierManagerUtils,EInvalidTierId));

    CCDTierRecord* tierRec = static_cast<CCDTierRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdTierRecord));
    CleanupStack::PushL(tierRec);

    tierRec->SetRecordId(aTierId);

	tierRec->LoadL(aDbs);

    if (static_cast<TInt>(tierRec->iDefaultAccessPoint)!=0)
        {
        TInt defTierElemId = ResolveDefAPtoTagL(static_cast<TInt>(tierRec->iDefaultAccessPoint), aDbs );
        tierRec->iDefaultAccessPoint = defTierElemId;
        }
	__ASSERT_DEBUG(tierRec->iTierManagerName.TypeId() == KCDTIdTierManagerName, User::Panic(KSpecAssert_ESockSSockTrMngU, 2)); // Panics if built against incorrect CommsDat.
	CleanupStack::Pop(tierRec);
	return tierRec;
	}

EXPORT_C CCDAPPrioritySelectionPolicyRecord* TierManagerUtils::LoadAPPrioritySelRecordL(CommsDat::TMDBElementId aApSelId, CommsDat::CMDBSession& aDbs)
	{
	__ASSERT_ALWAYS(aApSelId>0,User::Panic(KTierManagerUtils,EInvalidAPSelPolId));

    CCDAPPrioritySelectionPolicyRecord* apSelRec = static_cast<CCDAPPrioritySelectionPolicyRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdApPrioritySelectionPolicyRecord));
    CleanupStack::PushL(apSelRec);

    apSelRec->SetRecordId(aApSelId);

	apSelRec->LoadL(aDbs);

	CleanupStack::Pop(apSelRec);
	return apSelRec;
	}


EXPORT_C CCDAccessPointRecord* TierManagerUtils::LoadAccessPointRecordL(TUint aAccessPointId, CMDBSession& aDbs)
	{
	/**
	There are cases when ESock tries to load an access point record based on tag id but this id
	is got as a TUint parameter. The conversion is here.
	*/
	__ASSERT_ALWAYS(aAccessPointId>0,User::Panic(KTierManagerUtils,EInvalidAccessPointId));

	TUid temp;
	temp.iUid = aAccessPointId;
	return LoadAccessPointRecordL(temp, aDbs);
	}


EXPORT_C CCDAccessPointRecord* TierManagerUtils::LoadAccessPointRecordL(TUid aAccessPointId, CMDBSession& aDbs)
	{
	__ASSERT_ALWAYS(aAccessPointId.iUid>0,User::Panic(KTierManagerUtils,EInvalidAccessPointId));

    CCDAccessPointRecord* apRec = static_cast<CCDAccessPointRecord*>(CCDTierRecord::RecordFactoryL(KCDTIdAccessPointRecord));
	CleanupStack::PushL(apRec);
	apRec->iRecordTag = aAccessPointId.iUid;

	TBool found = apRec->FindL(aDbs);

	if (!found)
    	{
    	User::Leave(KErrNotFound);
    	}
	__ASSERT_DEBUG(apRec->iTier.TypeId() == KCDTIdTier, User::Panic(KSpecAssert_ESockSSockTrMngU, 3)); // Panics if built against incorrect CommsDat.
	CleanupStack::Pop(apRec);
	return apRec;
	}


EXPORT_C CCDAccessPointRecord* TierManagerUtils::LoadAccessPointRecordL(const TProviderInfo& aProviderInfo, CMDBSession& aDbs)
	{
	CCDAccessPointRecord* apRec = LoadAccessPointRecordL(aProviderInfo.APId(),aDbs);
	__ASSERT_DEBUG(aProviderInfo.TierId().iUid==apRec->iTier, User::Panic(KSpecAssert_ESockSSockTrMngU, 4));
	return apRec;
	}

EXPORT_C CMDBRecordSet<CCDAccessPointRecord>* TierManagerUtils::LoadAccessPointRecordsL(
							TUid aTierId, CMDBSession& aDbs)
	{
	__ASSERT_ALWAYS(aTierId.iUid>0,User::Panic(KTierManagerUtils,EInvalidTierId));

	//Load all AP records that belong to this tier.
	CMDBRecordSet<CCDAccessPointRecord>* apSet = new(ELeave) CMDBRecordSet<CCDAccessPointRecord>(KCDTIdAccessPointRecord);
    CleanupStack::PushL(apSet);

    //Create first record for priming
    CCDAccessPointRecord* apRec = static_cast<CCDAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord));
    CleanupStack::PushL(apRec);

    //Add record to record set
    apRec->iTier = aTierId.iUid | KEsockLinkFlag;
    apSet->iRecords.AppendL(apRec);
    CleanupStack::Pop(apRec);

    //Load set
    TBool returned = apSet->FindL(aDbs);

	//Check if apRec has been overwritten
    if( ! returned )
        {
		User::Leave(KErrNotFound);
        }

    CleanupStack::Pop(apSet);
	return apSet;
	}

EXPORT_C CMDBRecordSet<CCDAccessPointRecord>* TierManagerUtils::LoadAccessPointRecordsL(
							TUid aTierId, const RArray<TAccessPointInfo>& aApIdsToMatch, CMDBSession& aDbs)
	{
	if(aApIdsToMatch.Count())
		{
		CMDBRecordSet<CCDAccessPointRecord>* apSet = new(ELeave) CMDBRecordSet<CCDAccessPointRecord>(KCDTIdAccessPointRecord);
	    CleanupStack::PushL(apSet);

		CCDAccessPointRecord* apRec = 0;
		TInt i=0;
		for( ; i<aApIdsToMatch.Count() ; ++i )
			{
			if(apRec == 0)
				{
				apRec = static_cast<CCDAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord));
   				CleanupStack::PushL(apRec);
				}
  			apRec->iTier = aTierId.iUid | KEsockLinkFlag;

			apRec->iRecordTag = aApIdsToMatch[i].AccessPoint();
			TBool returned = apRec->FindL(aDbs);
			if(returned)
				{
			    apSet->iRecords.AppendL(apRec);
				CleanupStack::Pop(apRec);
				apRec = 0; // so a new one gets created on next iteration
				}
			}
		if(apRec)
			{
			CleanupStack::PopAndDestroy(apRec);
			}
		CleanupStack::Pop(apSet);
		return apSet;
		}
	else
		{
		// empty set means no filtering
		return LoadAccessPointRecordsL(aTierId,aDbs);
		}
	}

EXPORT_C CCDMCprRecord* TierManagerUtils::LoadMCprRecordL(TUint aMCprId, CMDBSession& aDbs)
	{
    CCDMCprRecord* mcprRec = static_cast<CCDMCprRecord*>(CCDMCprRecord::RecordFactoryL(KCDTIdMCprRecord));
	CleanupStack::PushL(mcprRec);

    mcprRec->SetRecordId(aMCprId);

	mcprRec->LoadL(aDbs);

	__ASSERT_DEBUG(mcprRec->iMCprUid.TypeId() == KCDTIdMCprUid, User::Panic(KSpecAssert_ESockSSockTrMngU, 5)); // Panics if built against incorrect CommsDat.
	CleanupStack::Pop(mcprRec);
	return mcprRec;
	}

EXPORT_C CCDMCprRecord* TierManagerUtils::LoadMCprRecordL(TUid aMCprFactoryUid, CMDBSession& aDbs)
	{
    CCDMCprRecord* mcprRec = static_cast<CCDMCprRecord*>(CCDMCprRecord::RecordFactoryL(KCDTIdMCprRecord));
	CleanupStack::PushL(mcprRec);
	mcprRec->iMCprUid = aMCprFactoryUid.iUid;
	TBool found = mcprRec->FindL(aDbs);

	if (!found)
    	{
    	User::Leave(KErrNotFound);
    	}
	__ASSERT_DEBUG(mcprRec->iMCprUid.TypeId() == KCDTIdMCprUid, User::Panic(KSpecAssert_ESockSSockTrMngU, 6)); // Panics if built against incorrect CommsDat.
	CleanupStack::Pop(mcprRec);
	return mcprRec;
	}

EXPORT_C CCDCprRecord* TierManagerUtils::LoadCprRecordL(TUint aCprId, CMDBSession& aDbs)
	{
	__ASSERT_ALWAYS(aCprId>0,User::Panic(KTierManagerUtils,EInvalidCprId));

    CCDCprRecord* cprRec = static_cast<CCDCprRecord*>(CCDCprRecord::RecordFactoryL(KCDTIdCprRecord));
	CleanupStack::PushL(cprRec);

    cprRec->SetRecordId(aCprId);

	cprRec->LoadL(aDbs);

	__ASSERT_DEBUG(cprRec->iCprUid.TypeId() == KCDTIdCprUid, User::Panic(KSpecAssert_ESockSSockTrMngU, 7)); // Panics if built against incorrect CommsDat.
	CleanupStack::Pop(cprRec);
	return cprRec;
	}

EXPORT_C CCDSCprRecord* TierManagerUtils::LoadSCprRecordL(TUint aSCprId, CMDBSession& aDbs)
	{
    __ASSERT_ALWAYS(aSCprId>0,User::Panic(KTierManagerUtils,EInvalidSCprId));

    CCDSCprRecord* scprRec = static_cast<CCDSCprRecord*>(CCDSCprRecord::RecordFactoryL(KCDTIdSCprRecord));
	CleanupStack::PushL(scprRec);

    scprRec->SetRecordId(aSCprId);

	scprRec->LoadL(aDbs);

	__ASSERT_DEBUG(scprRec->iSCprUid.TypeId() == KCDTIdSCprUid, User::Panic(KSpecAssert_ESockSSockTrMngU, 8)); // Panics if built against incorrect CommsDat.
	CleanupStack::Pop(scprRec);
	return scprRec;
	}

EXPORT_C CCDProtocolRecord* TierManagerUtils::LoadProtocolRecordL(TUint aProtocolId, CMDBSession& aDbs)
	{
	__ASSERT_ALWAYS(aProtocolId>0,User::Panic(KTierManagerUtils,EInvalidProtocolId));

    CCDProtocolRecord* prtRec = static_cast<CCDProtocolRecord*>(CCDTierRecord::RecordFactoryL(KCDTIdProtocolRecord));
	CleanupStack::PushL(prtRec);

	prtRec->SetRecordId(aProtocolId);

	prtRec->LoadL(aDbs);

	__ASSERT_DEBUG(prtRec->iProtocolUid.TypeId() == KCDTIdProtocolUid, User::Panic(KSpecAssert_ESockSSockTrMngU, 9)); // Panics if built against incorrect CommsDat.
	CleanupStack::Pop(prtRec);
	return prtRec;
	}

EXPORT_C CCDGlobalSettingsRecord* TierManagerUtils::LoadGlobalSettingsRecordL(CMDBSession& aDbs)
	{
	CCDGlobalSettingsRecord* gsRec = static_cast<CCDGlobalSettingsRecord*>(CCDGlobalSettingsRecord::RecordFactoryL(KCDTIdGlobalSettingsRecord));
	CleanupStack::PushL(gsRec);
	gsRec->SetRecordId(1);
	gsRec->LoadL(aDbs);
	__ASSERT_DEBUG(gsRec->iDefaultTier.TypeId() == KCDTIdDefaultTier, User::Panic(KSpecAssert_ESockSSockTrMngU, 10)); // Panics if built against incorrect CommsDat.
	CleanupStack::Pop(gsRec);
	return gsRec;
	}

EXPORT_C CCDIAPRecord* TierManagerUtils::LoadIapRecordL(TUint aIapId, CMDBSession& aDbs)
	{
	__ASSERT_ALWAYS(aIapId>0,User::Panic(KTierManagerUtils,EInvalidIapId));

	CCDIAPRecord* iapRec = static_cast<CCDIAPRecord*>(CCDIAPRecord::RecordFactoryL(KCDTIdIAPRecord));
	CleanupStack::PushL(iapRec);
	iapRec->SetRecordId(aIapId);
	iapRec->LoadL(aDbs);
	CleanupStack::Pop(iapRec);
	return iapRec;
	}

EXPORT_C CMDBRecordSet<CCDIAPRecord>* TierManagerUtils::LoadIapRecordsL(CMDBSession& aDbs)
	{
	//Load all IAP records
	CMDBRecordSet<CCDIAPRecord>* iapSet = new(ELeave) CMDBRecordSet<CCDIAPRecord>(KCDTIdIAPRecord);
    CleanupStack::PushL(iapSet);

    //Create first record for priming
	CCDIAPRecord* iapRec = static_cast<CCDIAPRecord*>(CCDIAPRecord::RecordFactoryL(KCDTIdIAPRecord));
	CleanupStack::PushL(iapRec);

    //Add record to record set
    iapSet->iRecords.AppendL(iapRec);
    CleanupStack::Pop(iapRec);

    //Load set
    TBool returned = iapSet->FindL(aDbs);

	//Check if apRec has been overwritten
    if( ! returned )
        {
		User::Leave(KErrNotFound);
        }

    CleanupStack::Pop(iapSet);
	return iapSet;
	}

EXPORT_C TUint TierManagerUtils::ReadDefaultAccessPointL(TUid aTierId, CMDBSession& aDbs)
	{
	CCDTierRecord* tierRec = TierManagerUtils::LoadTierRecordL(aTierId,aDbs);
	TUint accessPoint = tierRec->iDefaultAccessPoint;
	delete tierRec;
	return accessPoint;
	}

EXPORT_C TUid TierManagerUtils::ReadTierIdL(TUint aAccessPointId, CMDBSession& aDbs)
	{

	//it would be better to load 2 fields rather than load 2 record....

	__ASSERT_ALWAYS(aAccessPointId>0,User::Panic(KTierManagerUtils,EInvalidAccessPointId));

	CCDAccessPointRecord* apRec = TierManagerUtils::LoadAccessPointRecordL(aAccessPointId,aDbs);

	CleanupStack::PushL(apRec);

	//load the tag field for the given tier record
	CMDBField<TInt>* iRecordTag = new (ELeave) CMDBField<TInt>(static_cast<TInt>(apRec->iTier) | KCDTIdRecordTag);
    CleanupStack::PushL(iRecordTag);

    iRecordTag->LoadL(aDbs);

	TInt tempTag = *iRecordTag;
	CleanupStack::PopAndDestroy(iRecordTag);

	TUid tierId = TUid::Uid(tempTag);

	CleanupStack::PopAndDestroy(apRec);
	//delete apRec;
	User::LeaveIfError(tierId.iUid? KErrNone : KErrCorrupt);
	return tierId;
	}

EXPORT_C TUid TierManagerUtils::ReadMCprUidL(TUint aAccessPointId, CMDBSession& aDbs)
	{
	__ASSERT_ALWAYS(aAccessPointId>0,User::Panic(KTierManagerUtils,EInvalidAccessPointId));

	CCDAccessPointRecord* apRec = TierManagerUtils::LoadAccessPointRecordL(aAccessPointId,aDbs);
	CleanupStack::PushL(apRec);
	CCDMCprRecord* mcprRec = TierManagerUtils::LoadMCprRecordL(apRec->iMCpr,aDbs);
	TUid mCprUid = TUid::Uid(mcprRec->iMCprUid);
	delete mcprRec;
	CleanupStack::PopAndDestroy(apRec);
	return mCprUid;
	}

EXPORT_C TUint TierManagerUtils::ReadSelectionPolicyIdL(TUint aAccessPointId, CMDBSession& aDbs)
	{
	__ASSERT_ALWAYS(aAccessPointId>0,User::Panic(KTierManagerUtils,EInvalidAccessPointId));

	CCDAccessPointRecord* apRec = TierManagerUtils::LoadAccessPointRecordL(aAccessPointId,aDbs);
	TUint policyId = apRec->iSelectionPolicy;
	delete apRec;
	return policyId;
	}

EXPORT_C TUint TierManagerUtils::ReadCustomSelectionPolicyIdL(TUint aAccessPointId, CommsDat::CMDBSession& aDbs)
    {
    __ASSERT_ALWAYS(aAccessPointId>0,User::Panic(KTierManagerUtils,EInvalidAccessPointId));

	CCDAccessPointRecord* apRec = TierManagerUtils::LoadAccessPointRecordL(aAccessPointId,aDbs);
	TUint customSelPolicyId = apRec->iCustomSelectionPolicy;
	delete apRec;
	return customSelPolicyId;
    }

EXPORT_C TUint TierManagerUtils::ReadCprConfigL(TUint aAccessPointId, CMDBSession& aDbs)
	{
	__ASSERT_ALWAYS(aAccessPointId>0,User::Panic(KTierManagerUtils,EInvalidAccessPointId));

	CCDAccessPointRecord* apRec = TierManagerUtils::LoadAccessPointRecordL(aAccessPointId,aDbs);
	TUint cprconfig = apRec->iCprConfig;
	delete apRec;
	return cprconfig;
	}

EXPORT_C ESock::RTierThreadMap* TierManagerUtils::BuildTierThreadMappingL(CMDBSession& aDbs)
	{
	RTierThreadMap* map = new (ELeave) RTierThreadMap;
	CleanupClosePushL(*map);
	CMDBRecordSet<CCDTierRecord>* recSet = new (ELeave) CMDBRecordSet<CCDTierRecord>(KCDTIdTierRecord);
	CleanupStack::PushL(recSet);
	recSet->LoadL(aDbs);
	CommsFW::TCFModuleName narrowThreadName;
	const TInt recCnt = recSet->iRecords.Count();
	for(TInt i = 0; i < recCnt; ++i)
		{
		CCDTierRecord* rec = static_cast<CCDTierRecord*>(recSet->iRecords[i]);
		narrowThreadName.Copy(rec->iTierThreadName);
		TWorkerId worker;
		if(!CWorkerThread::ResolveWorkerNameToId(narrowThreadName, worker))
			{
			LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("TierManagerUtils::BuildTierThreadMappingL - worker name %S failed resolution"), &narrowThreadName));
			continue;
			}
		map->AppendL(TTierMapEntry(rec->iRecordTag, worker));
		}
	CleanupStack::PopAndDestroy(recSet);
	CleanupStack::Pop(map);
	return map;
	}

//This function reads the IAP priority based selection policy table (CCDIAPPrioritySelectionPolicyRecord)
//and fills the TConnIdList provided using the specified selectionPolicy (record id within the table).
EXPORT_C void TierManagerUtils::FillListL(TConnIdList& aList, TUint selectionPolicy, CMDBSession& aDbs)
	{
	LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("TierManagerUtils::FillListL()")));

	//The provided list must be empty.
	__ASSERT_DEBUG(aList.Count()==0, User::Panic(KSpecAssert_ESockSSockTrMngU, 11));

	CCDAPPrioritySelectionPolicyRecord* policyRec = static_cast<CCDAPPrioritySelectionPolicyRecord*>
		(CCDConnectionPrefsRecord::RecordFactoryL(KCDTIdApPrioritySelectionPolicyRecord));
	CleanupStack::PushL(policyRec);
	policyRec->SetRecordId(selectionPolicy);
	policyRec->LoadL(aDbs);

//	CMDBField<TUint32>* theAp = &policyRec->iAp1;
	CMDBRecordLink<CCDAccessPointRecord>* theAp = &policyRec->iAp1;
	TUint32 theCount = policyRec->iApCount;
	__ASSERT_DEBUG(theCount <= CCDAPPrioritySelectionPolicyRecord::EMaxNrOfAps, User::Panic(KSpecAssert_ESockSSockTrMngU, 12));

	for (TInt i = 0; i < theCount; i++, theAp++)
		{
		//TInt apId = static_cast<TInt>(*theAp);
		TInt apId = ResolveDefAPtoTagL((*theAp), aDbs );
		__ASSERT_DEBUG(apId>0, User::Panic(KSpecAssert_ESockSSockTrMngU, 13));
		LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ListCount[%d] Append(%d)"),aList.Count(),apId));
		aList.Append(apId);
		}

	CleanupStack::PopAndDestroy(policyRec);
	}

//This function reads the AP priority based selection policy table (CCDAPPrioritySelectionPolicyRecord)
//and fills the RConnPrefList provided using the specified selectionPolicy (record id within the table).
EXPORT_C void TierManagerUtils::FillListL(RConnPrefList& aList, TUint selectionPolicy, CMDBSession& aDbs)
	{
	LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("TierManagerUtils::FillListL()")));

	CCDAPPrioritySelectionPolicyRecord* policyRec = static_cast<CCDAPPrioritySelectionPolicyRecord*>
		(CCDConnectionPrefsRecord::RecordFactoryL(KCDTIdApPrioritySelectionPolicyRecord));
	CleanupStack::PushL(policyRec);
	policyRec->SetRecordId(selectionPolicy);
	policyRec->LoadL(aDbs);

	CMDBRecordLink<CCDAccessPointRecord>* theAp = &policyRec->iAp1;
	TUint32 theCount = policyRec->iApCount;
	__ASSERT_DEBUG(theCount <= CCDAPPrioritySelectionPolicyRecord::EMaxNrOfAps, User::Panic(KSpecAssert_ESockSSockTrMngU, 14));

	for (TInt i = 0; i < theCount; i++, theAp++)
		{
		TInt apId = ResolveDefAPtoTagL((*theAp), aDbs );
		TConnAPPref* pref = TConnAPPref::NewL(apId);
		CleanupStack::PushL(pref);
		__ASSERT_DEBUG(apId>0, User::Panic(KSpecAssert_ESockSSockTrMngU, 15));
		LOG(ESockLog::Printf(KESockMetaConnectionTag, _L("ListCount[%d] Append(%d)"),aList.Count(),apId));
		aList.AppendL(pref);
		CleanupStack::Pop();
		}

	CleanupStack::PopAndDestroy(policyRec);
	}

EXPORT_C TUint TierManagerUtils::GetConnectionAttemptsL(CMDBSession& aDbs)
	{
	//it's enough to load the appropriate field...
	CCDGlobalSettingsRecord* glRec = TierManagerUtils::LoadGlobalSettingsRecordL(aDbs);
	CleanupStack::PushL(glRec);
	TUint connectionAttempts = glRec->iMaxConnectionAttempts;
	CleanupStack::PopAndDestroy(glRec);
	return connectionAttempts;
	}

EXPORT_C void TierManagerUtils::MapRankingToPrefsL(TUint aRanking, TCommDbConnPref& aPrefs, CMDBSession& aDbs)
	{
	CCDConnectionPrefsRecord* cpRec = static_cast<CCDConnectionPrefsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord));
	CleanupStack::PushL(cpRec);
	cpRec->iRanking = aRanking;
	TBool found = cpRec->FindL(aDbs);
	if (!found)
    	{ //CommsDat API is a widely known problem
    	User::Leave(KErrNotFound);
    	}

	//CommDat records do not like to be casted, this is why we have double cast here.. (!?!)
	aPrefs.SetIapId(cpRec->iDefaultIAP);
	aPrefs.SetDialogPreference(static_cast<TCommDbDialogPref>((TUint)cpRec->iDialogPref));
	aPrefs.SetDirection(static_cast<TCommDbConnectionDirection>((TUint)cpRec->iDirection));
	aPrefs.SetBearerSet(cpRec->iBearerSet);

	CleanupStack::PopAndDestroy(cpRec);
	}

EXPORT_C void TierManagerUtils::ParseTLConfigAccessPointIdsL(RArray<TUint> &aIds, const TDesC& aIdList)
    {
    TLex lexer(aIdList);
    while (!lexer.Eos())
	{
	TUint val = 0;
	TInt err = lexer.Val(val);
	if (err != KErrNone)
	    User::Leave(KErrArgument);
	aIds.AppendL(val);

	lexer.SkipSpaceAndMark();
	if (lexer.Peek() == ',')
	    lexer.Inc();
	}
    }

EXPORT_C CCDConfigAccessPointRecord* TierManagerUtils::LoadConfigAccessPointRecordL(TUint aId, CommsDat::CMDBSession& aDBs)
    {
    CCDConfigAccessPointRecord* capRec = static_cast<CCDConfigAccessPointRecord*>(CCDConfigAccessPointRecord::RecordFactoryL(KCDTIdConfigAccessPointRecord));

    CleanupStack::PushL(capRec);
    capRec->SetRecordId(aId);
    capRec->LoadL(aDBs);

    CleanupStack::Pop(capRec);
    return capRec;
    }

EXPORT_C void TierManagerUtils::MapRankingAndDirectionToPrefsL(TUint aRanking, TCommDbConnectionDirection aDirection, TCommDbConnPref& aPrefs, CMDBSession& aDbs)
	{
	CCDConnectionPrefsRecord* cpRec = static_cast<CCDConnectionPrefsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord));
	CleanupStack::PushL(cpRec);
	cpRec->iRanking = aRanking;
	cpRec->iDirection = aDirection;

	TBool found = cpRec->FindL(aDbs);
	if (!found)
    	{
    	User::Leave(KErrNotFound);
    	}

	//CommDat records do not like to be casted, this is why we have double cast here.. (!?!)
	aPrefs.SetIapId(cpRec->iDefaultIAP);
	aPrefs.SetDialogPreference(static_cast<TCommDbDialogPref>((TUint)cpRec->iDialogPref));
	aPrefs.SetDirection(static_cast<TCommDbConnectionDirection>((TUint)cpRec->iDirection));
	aPrefs.SetBearerSet(cpRec->iBearerSet);

	CleanupStack::PopAndDestroy(cpRec);
	}

EXPORT_C  void TierManagerUtils::GetPrefsFromConnPrefRecL(TUint aConnPrefRecElemId,
											  			  CommsDat::CMDBSession& aDbs,
											  			  TConnectionPrefs& aConnPrefs)
	{
	CCDConnectionPrefsRecord* cpRec = static_cast<CCDConnectionPrefsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord));
	CleanupStack::PushL(cpRec);
	cpRec->SetElementId(aConnPrefRecElemId);

	cpRec->LoadL(aDbs);

	aConnPrefs.iRank = cpRec->iRanking;
	aConnPrefs.iDirection = cpRec->iDirection;
	aConnPrefs.iBearerSet = cpRec->iBearerSet;

	CleanupStack::PopAndDestroy(cpRec);
	}

EXPORT_C TUid TierManagerUtils::MapTierIdtoTierImplIdL(TUid aTierUid,CommsDat::CMDBSession& aDbs )
/** mapping TM Id to TM ImplId in Commsdat */
	{
	TUid ImplUid;
	// if it does not exist, it returns tier id
	ImplUid = aTierUid;

	CMDBRecordSet<CCDTierRecord>* recSet = new (ELeave) CMDBRecordSet<CCDTierRecord>(KCDTIdTierRecord);
	CleanupStack::PushL(recSet);
	recSet->LoadL(aDbs);
	const TInt recCnt = recSet->iRecords.Count();
	
	for(TInt i = 0; i < recCnt; i++)
		{
		CCDTierRecord* rec = static_cast<CCDTierRecord*>(recSet->iRecords[i]);
		if(rec->iRecordTag == aTierUid.iUid)
			{
			ImplUid.iUid = rec->iTierImplUid;
			}
		}
	
	CleanupStack::PopAndDestroy(recSet);	
	return ImplUid;
	}
//
// CCommsDatIapView
//
// Class used to retrieve CommsDat values based on a view specific to an IAP.
//

EXPORT_C CCommsDatIapView* CCommsDatIapView::NewL(TUint aIapId)
/**
Create a new IAP view object based on the IAP number specified.

@param aIapId IAP number
@return IAP view object
*/
	{
	CCommsDatIapView* self = new (ELeave) CCommsDatIapView();
	CleanupStack::PushL(self);

	// Second phase construction
	self->iDbs = CMDBSession::NewL(KCDVersion1_2);

	// Reveal hidden or private IAP records if a licensee has chosen to protect a record
	// using one of these flags - the API to do this is public so internal components
	// have to support the use of such records.
	self->iDbs->SetAttributeMask( ECDHidden | ECDPrivate );

	self->iIapRec = TierManagerUtils::LoadIapRecordL(aIapId, *self->iDbs);
	self->iUmtsR99QoSAndOnRecId = -1;

	CleanupStack::Pop(self);
	return self;
	}

EXPORT_C CCommsDatIapView* CCommsDatIapView::NewLC(TUint aIapId)
/**
Create a new IAP view object based on the IAP number specified, and leave
a cleanup item on the cleanup stack.

@param aIapId IAP number
@return IAP view object
*/
	{
	CCommsDatIapView* self = NewL(aIapId);
	CleanupStack::PushL(self);
	return self;
	}

EXPORT_C CCommsDatIapView::~CCommsDatIapView()
	{
	delete iBool;
	delete iUint;
	delete iInt;
	delete iText8;
	delete iText16;

	delete iIapRec;
	delete iDbs;
	}


/**
Retrieve an unsigned integer value from CommsDat.

@param aElementId element id of the field required.  The record id does not need to be specified.
This field can take the special value KCDTIdIAPNetwork to retrieve the Network Id.
@param aValue returned integer value
*/
EXPORT_C void CCommsDatIapView::GetIntL(TMDBElementId aElementId, TUint32& aValue)
	{
	if ((aElementId & KCDMaskShowRecordType) == KCDTIdIAPRecord)
		{
		GetIapRecordIntL(aElementId, aValue);
		return;
		}

	if (iUint == NULL)
		{
		iUint = new (ELeave) CMDBField<TUint32>();
		}
	SetElementAndRecordIdL(iUint, aElementId);

	IntFieldTypeCheckL(iUint->ElementId());

	iUint->LoadL(*iDbs);
	aValue = *iUint;
	}


/**
Retrieve an unsigned integer value from CommsDat (non-leaving)

@param aElementId element id of the field required.  The record id does not need to be specified.
@param aValue returned integer value
@return KErrNone or a system wide error code
*/
EXPORT_C TInt CCommsDatIapView::GetInt(TMDBElementId aElementId, TUint32& aValue)
	{
	TRAPD(err, GetIntL(aElementId, aValue));
	return err;
	}


/**
Retrieve a signed integer value from CommsDat.

@param aElementId element id of the field required.  The record id does not need to be specified.
This field can take the special value KCDTIdIAPNetwork to retrieve the Network Id.
@param aValue returned integer value
*/
EXPORT_C void CCommsDatIapView::GetIntL(TMDBElementId aElementId, TInt& aValue)
	{
	if ((aElementId & KCDMaskShowRecordType) == KCDTIdIAPRecord)
		{
		GetIapRecordIntL(aElementId, aValue);
		return;
		}

	if (iInt == NULL)
		{
		iInt = new (ELeave) CMDBField<TInt>();
		}
	SetElementAndRecordIdL(iInt, aElementId);

	IntFieldTypeCheckL(iInt->ElementId());

	iInt->LoadL(*iDbs);
	aValue = *iInt;
	}


/**
Retrieve a signed integer value from CommsDat (non-leaving)

@param aElementId element id of the field required.  The record id does not need to be specified.
@param aValue returned integer value
@return KErrNone or a system wide error code
*/
EXPORT_C TInt CCommsDatIapView::GetInt(TMDBElementId aElementId, TInt& aValue)
	{
	TRAPD(err, GetIntL(aElementId, aValue));
	return err;
	}


/**
Retrieve a boolean value from CommsDat

@param aElementId element id of the field required.  The record id does not need to be specified.
@param aValue returned boolean value
*/
EXPORT_C void CCommsDatIapView::GetBoolL(TMDBElementId aElementId, TBool& aValue)
	{
	if (NULL == iBool)
		{
		iBool = new (ELeave) CMDBField<TBool>();
		}
	SetElementAndRecordIdL(iBool, aElementId);

	BoolFieldTypeCheckL(iBool->ElementId());

	iBool->LoadL(*iDbs);
	aValue = *iBool;
	}


/**
Retrieve a boolean value from CommsDat (non-leaving)

@param aElementId element id of the field required.  The record id does not need to be specified.
@param aValue returned boolean value
@return KErrNone or a system wide error code
*/
EXPORT_C TInt CCommsDatIapView::GetBool(TMDBElementId aElementId, TBool& aValue)
	{
	TRAPD(err, GetBoolL(aElementId, aValue));
	return err;
	}


/**
Retrieve a text value from CommsDat

@param aElementId element id of the field required.  The record id does not need to be specified.
@param aValue In this field the caller receives ownership of a HBufC containing the text value.
The following function will read in 8 bit text and output 16 bit convertion to keep up with legacy behaviour
*/
EXPORT_C void CCommsDatIapView::GetTextL(TMDBElementId aElementId, HBufC8*& aValue)
	{
    aValue = NULL;
    if (NULL == iText8)
        {
        iText8 = new (ELeave) CMDBField<TDesC8>();
        }
    SetElementAndRecordIdL(iText8, aElementId);

    TextOrBinFieldTypeCheckL(iText8->ElementId());

    TRAPD(err, iText8->LoadL(*iDbs)); // trap first attempt for retry with larger buffer
    if (err == KErrOverflow)
        {
        iText8->SetMaxLengthL(1024);
        iText8->LoadL(*iDbs);
        err = KErrNone;
        }
    User::LeaveIfError(err);

    CMDBRecordBase* recordBase = CCDRecordBase::RecordFactoryL(iText8->TableId());
	CleanupStack::PushL(recordBase);
	CMDBElement* el = recordBase->GetFieldByIdL(iText8->TypeId());
	if (EText == el->Type())
		{
		const TDesC8& des8 = iText8->GetL();
		TPtrC ptr16(reinterpret_cast<const TUint16 *>(des8.Ptr()), des8.Length() / 2);
	    // Create a HBufC to return to the caller, containing a copy of the field.
	    aValue = HBufC8::NewMaxL(ptr16.Length());
		aValue->Des().Copy(ptr16);
		}
    else
	   {
	    // Create a HBufC to return to the caller, containing a copy of the field.
	    aValue = HBufC8::NewMaxL(static_cast<const TDesC8&>(*iText8).Length());
	    *aValue = *iText8;
	   }

	CleanupStack::PopAndDestroy(recordBase);
	}


/**
Retrieve a text value from CommsDat (non-leaving)

@param aElementId element id of the field required.  The record id does not need to be specified.
@param aValue In this field the caller receives ownership of a HBufC containing the text value.
@return KErrNone or a system wide error code
The following function will read in 16 bit text and output 8 bit convertion to keep up with legacy behaviour
*/
EXPORT_C TInt CCommsDatIapView::GetText(TMDBElementId aElementId, HBufC8*& aValue)
	{
	TRAPD(err, GetTextL(aElementId, aValue));
	return err;
	}


/**
Retrieve a text value from CommsDat

@param aElementId element id of the field required.  The record id does not need to be specified.
@param aValue In this field the caller receives ownership of a HBufC containing the text value.
*/

EXPORT_C void CCommsDatIapView::GetTextL(TMDBElementId aElementId, HBufC16*& aValue)
	{
	if ((aElementId & KCDMaskShowRecordType) == KCDTIdIAPRecord)
		{
		GetIapRecordTextL(aElementId, aValue);
		return;
		}

	aValue = NULL;
    if (NULL == iText16)
        {
        iText16 = new (ELeave) CMDBField<TDesC16>();
        }
    SetElementAndRecordIdL(iText16, aElementId);

    TextOrBinFieldTypeCheckL(iText16->ElementId());

    TRAPD(err, iText16->LoadL(*iDbs)); // trap first attempt for retry with larger buffer
    if (err == KErrOverflow)
        {
        iText16->SetMaxLengthL(1024);
        iText16->LoadL(*iDbs);
        err = KErrNone;
        }
    User::LeaveIfError(err);

    CMDBRecordBase* recordBase = CCDRecordBase::RecordFactoryL(iText16->TableId());
	CleanupStack::PushL(recordBase);
	CMDBElement* el = recordBase->GetFieldByIdL(iText16->TypeId());
	if (EDesC8 == el->Type())
		{
		const TDesC16& des16 = iText16->GetL();
		TPtrC8 ptr8(reinterpret_cast<const TUint8 *>(des16.Ptr()), des16.Size());

	    // Create a HBufC to return to the caller, containing a copy of the field.
	    aValue = HBufC16::NewMaxL(ptr8.Length());
		aValue->Des().Copy(ptr8);
		}
    else
	   {
	    // Create a HBufC to return to the caller, containing a copy of the field.
	    aValue = HBufC16::NewMaxL(static_cast<const TDesC16&>(*iText16).Length());
	    *aValue = *iText16;
	   }

	CleanupStack::PopAndDestroy(recordBase);
	}


/**
Retrieve a text value from CommsDat (non-leaving)

@param aElementId element id of the field required.  The record id does not need to be specified.
@param aValue In this field the caller receives ownership of a HBufC containing the text value.
@return KErrNone or a system wide error code
*/
EXPORT_C TInt CCommsDatIapView::GetText(TMDBElementId aElementId, HBufC16*& aValue)
	{
	TRAPD(err, GetTextL(aElementId, aValue));
	return err;
	}


void CCommsDatIapView::GetIapRecordIntL(TMDBElementId aElementId, TUint32& aValue)
	{
	switch(aElementId)
		{
		case (KCDTIdIAPRecord | KCDTIdRecordTag):
			aValue = iIapRec->iRecordTag;
			break;

		case KCDTIdIAPService:
			aValue = iIapRec->iService;
			break;

		case KCDTIdIAPBearer:
			aValue = iIapRec->iBearer;
			break;

		case KCDTIdIAPNetwork:
			aValue = iIapRec->iNetwork;
			break;

		case KCDTIdIAPNetworkWeighting:
			aValue = iIapRec->iNetworkWeighting;
			break;

		case KCDTIdIAPLocation:
			aValue = iIapRec->iLocation;
			break;

		case KCDTIdIAPAppSid:
			aValue = iIapRec->iAppSid;
			break;

		case KCDTIdRealIAP:
			{
			const TDesC& serviceType = iIapRec->iServiceType;
			if (serviceType.Compare(TPtrC(KCDTypeNameVPNService)) == 0)
				{
				GetIntL(KCDTIdVPNIAPRecord, aValue);
				}
			else
				{
				aValue = iIapRec->iRecordTag;
				}
			}
			break;

		default:
			{
			User::Leave(KErrBadName);
			}
		}
	}


void CCommsDatIapView::GetIapRecordIntL(TMDBElementId aElementId, TInt& aValue)
	{
	// Ok since this table only contains Uints, but none that
	// tickle the top bit
	TUint32 value;
	GetIapRecordIntL(aElementId, value);
	aValue = (TInt)value;
	}


void CCommsDatIapView::GetIapRecordTextL(TMDBElementId aElementId, HBufC16*& aValue)
	{
	switch(aElementId)
		{
		case (KCDTIdIAPRecord | KCDTIdRecordName):
			{
			const TDesC16& record = iIapRec->iRecordName;
			aValue = HBufC16::NewMaxL(record.Length());
			*aValue = record;
			}
			break;

		case KCDTIdIAPBearerType:
			{
			const TDesC16& record = iIapRec->iBearerType;
			aValue = HBufC16::NewMaxL(record.Length());
			*aValue = record;
			}
			break;

		case KCDTIdIAPServiceType:
			{
			const TDesC16& record = iIapRec->iServiceType;
			aValue = HBufC16::NewMaxL(record.Length());
			*aValue = record;
			}
			break;

		default:
			{
			User::Leave(KErrBadName);
			}
		}
	}


EXPORT_C TUint CCommsDatIapView::IapId()
/**
Return the IAP number associated with this IAP view object.
*/
	{
	//normally iRecordTag will be empty and anyway is not intended to hold the record id.
	// assuming the record id of the IAP is what is needed this call needs to be different
	//return iIapRec->iRecordTag;
	return iIapRec->RecordId();

	}

EXPORT_C CommsDat::TMDBElementId CCommsDatIapView::GetServiceTableType() const
    {
    CommsDat::TMDBElementId el;
    TInt err = ConvertServiceTypeToTableId(iIapRec->iServiceType,el);
    __ASSERT_DEBUG(err == KErrNone, User::Panic(KSpecAssert_ESockSSockTrMngU, 16));
    return el;
    }

EXPORT_C CommsDat::TMDBElementId CCommsDatIapView::GetBearerTableType() const
    {
    CommsDat::TMDBElementId el;
    TInt err = ConvertBearerTypeToTableId(iIapRec->iBearerType, el);
    __ASSERT_DEBUG(err == KErrNone, User::Panic(KSpecAssert_ESockSSockTrMngU, 17));
    return el;
    }


EXPORT_C void CCommsDatIapView::GetTableCommonTextFieldL(CCommsDatIapView::TFieldId aField, HBufC*& aValue)
/**
Generalised routine for reading the value of a specified text field from the current bearer or
service table.

The caller does not need to specify the particular CommsDat id.  In some ways this is similar
functionality to the CommsDat ability to read a field by name, but that mechanism was considered
too inefficient as this routine is likely to be called on every connection startup.

This routine does the work of determining the CommsDat id of the field with respect to the
current service or bearer table.

@param aElementId element id of the field required.  The record id does not need to be specified.
@param aValue In this field the caller receives ownership of a HBufC containing the text value.
*/
	{
	TMDBElementId el = 0;

	// Determine the CommsDat id of the field.
	switch (aField)
		{
	case EIfNetworks:
		switch (GetServiceTableType())
			{
		case KCDTIdDialOutISPRecord:
			el = KCDTIdIfNetworks;
			break;

		case KCDTIdOutgoingGprsRecord:
        case KCDTIdIncomingGprsRecord:
			el = KCDTIdWCDMAIfNetworks | GetServiceTableType();
			break;

		case KCDTIdLANServiceRecord:
			el = KCDTIdLANIfNetworks;
			break;

		case KCDTIdDialInISPRecord:
			el = KCDTIdDINIfNetworks;
			break;

		default:
			User::Leave(KErrCorrupt);
			} // inner switch
		break;
	case EConfigDaemonManagerName:
		switch (GetServiceTableType())
			{
		case KCDTIdDialOutISPRecord:
			el = KCDTIdConfigDaemonManagerName;
			break;

		case KCDTIdOutgoingGprsRecord:
        case KCDTIdIncomingGprsRecord:
			el = KCDTIdWCDMAConfigDaemonManagerName | GetServiceTableType();
			break;

		case KCDTIdLANServiceRecord:
			el = KCDTIdLANConfigDaemonManagerName;
			break;

		default:
			User::Leave(KErrCorrupt);
			} // inner switch
		break;
	case EConfigDaemonName:
		switch (GetServiceTableType())
			{
		case KCDTIdDialOutISPRecord:
			el = KCDTIdConfigDaemonName;
			break;

		case KCDTIdOutgoingGprsRecord:
        case KCDTIdIncomingGprsRecord:
			el = KCDTIdWCDMAConfigDaemonName | GetServiceTableType();
			break;

		case KCDTIdLANServiceRecord:
			el = KCDTIdLANConfigDaemonName;
			break;

		default:
			User::Leave(KErrCorrupt);
			} // inner switch
		break;
		} // outer switch

	GetTextL(el, aValue);
	}

EXPORT_C void CCommsDatIapView::GetTimeoutValuesL(TUint32& aShortTimeout, TUint32& aMediumTimeout, TUint32& aLongTimeout)
/**
Retrieve the idle timeout values based on the current IAP view.

@param aShortTimeout populated with LastSessionClosedTimeout field
@param aMediumTimeout populated with LastSocketClosedTimeout field
@param aLongTimeout populated with LastSocketActivityTimeout field
*/
	{
	TMDBElementId shortId = 0;
	TMDBElementId mediumId = 0;
	TMDBElementId longId = 0;

	//
	// Check the bearer type and setup the correct elementId's for the timeout fields
	//
	const TDesC& bearerType = iIapRec->iBearerType;
	if (bearerType.Compare(TPtrC(KCDTypeNameModemBearer)) == 0)
		{
	    longId = KCDTIdLastSocketActivityTimeout;
		shortId = KCDTIdLastSessionClosedTimeout;
		mediumId = KCDTIdLastSocketClosedTimeout;
		}
	else
	if (bearerType.Compare(TPtrC(KCDTypeNameLANBearer)) == 0)
		{
	    longId = KCDTIdLANLastSocketActivityTimeout;
		shortId = KCDTIdLANLastSessionClosedTimeout;
		mediumId = KCDTIdLANLastSocketClosedTimeout;
		}
	else
	if (bearerType.Compare(TPtrC(KCDTypeNameVirtualBearer)) == 0)
		{
	    longId = KCDTIdVBLastSocketActivityTimeout;
		shortId = KCDTIdVBLastSessionClosedTimeout;
		mediumId = KCDTIdVBLastSocketClosedTimeout;
		}
	else
		{
		User::Leave(KErrCorrupt);
		}

	// Retrieve the timeout fields
	GetIntL(longId, aLongTimeout);
	GetIntL(mediumId, aMediumTimeout);
	GetIntL(shortId, aShortTimeout);
	}

void CCommsDatIapView::SetElementAndRecordIdL(CMDBElement* aElement, TMDBElementId aElementId)
/**
Set the elementid of an element based on the current IAP view.

Essentially, this routine selects the service/bearer table entry to be retrieved,
based on the IAP specified.
*/
	{
	const TDesC& bearerType = iIapRec->iBearerType;
	const TDesC& serviceType = iIapRec->iServiceType;

	aElement->SetElementId(aElementId);
	TInt recordId = -1;

    if (aElementId == KCDTIdBearerAgent)
        {
        // Special case for reading the Agent name.  We have to determine the tableId
        // (by comparison of bearerType string) and then set the recordId from the
        // bearer record number.
        TMDBElementId tableId = 0;
        User::LeaveIfError(ConvertBearerTypeToTableId(bearerType, tableId));
        aElement->SetTypeId(KCDTIdBearerAgent | tableId);
        recordId = iIapRec->iBearer;
        }
    else
        {
        TInt elementId = aElement->TableId();
    	switch (elementId) // note: relies on above SetElementId() having been called
    		{
    	case KCDTIdGlobalSettingsRecord:
    		recordId = 1; // only one record for global settings table
    		break;

    	//Location Tables
    	case KCDTIdLocationRecord:
    		recordId = iIapRec->iLocation;
    	    break;


    	// Service Tables
    	case KCDTIdDialOutISPRecord:
    	    if (serviceType.Compare(TPtrC(KCDTypeNameDialOutISP)) == 0)
    	        {
        	    recordId = iIapRec->iService;
    	        }
    	    break;

    	case KCDTIdDialInISPRecord:
    	    if (serviceType.Compare(TPtrC(KCDTypeNameDialInISP)) == 0)
    	        {
        	    recordId = iIapRec->iService;
    	        }
    	    break;

    	case KCDTIdLANServiceRecord:
    	    if (serviceType.Compare(TPtrC(KCDTypeNameLANService)) == 0)
    	        {
        	    recordId = iIapRec->iService;
    	        }
    	    break;

    	case KCDTIdVPNServiceRecord:
    	    if (serviceType.Compare(TPtrC(KCDTypeNameVPNService)) == 0)
    	        {
        	    recordId = iIapRec->iService;
    	        }
    	    break;

        case KCDTIdOutgoingGprsRecord:
        case KCDTIdIncomingGprsRecord:
    	    if (serviceType.Compare(TPtrC(KCDTypeNameOutgoingWCDMA)) == 0 ||
    	        serviceType.Compare(TPtrC(KCDTypeNameIncomingWCDMA)) == 0 )
    	        {
        	    recordId = iIapRec->iService;
    	        }
    	    break;

        // Bearer Tables
    	case KCDTIdModemBearerRecord:
    	    if (bearerType.Compare(TPtrC(KCDTypeNameModemBearer)) == 0)
    	        {
        	    recordId = iIapRec->iBearer;
    	        }
    	    break;

    	case KCDTIdLANBearerRecord:
    	    if (bearerType.Compare(TPtrC(KCDTypeNameLANBearer)) == 0)
    	        {
        	    recordId = iIapRec->iBearer;
    	        }
    	    break;

    	case KCDTIdVirtualBearerRecord:
    	    if (bearerType.Compare(TPtrC(KCDTypeNameVirtualBearer)) == 0)
    	        {
        	    recordId = iIapRec->iBearer;
    	        }
    	    break;


        // Other tables
        case KCDTIdUmtsR99QoSAndOnTableRecord:
    	    if (serviceType.Compare(TPtrC(KCDTypeNameOutgoingWCDMA)) == 0 ||
    	        serviceType.Compare(TPtrC(KCDTypeNameIncomingWCDMA)) == 0 )
    	        {
    	        if (iUmtsR99QoSAndOnRecId == -1)
        	        {
                    CCDOutgoingGprsRecord* packetRec = static_cast<CCDOutgoingGprsRecord*>
                                        (CCDRecordBase::RecordFactoryL(KCDTIdOutgoingGprsRecord));
                    CleanupStack::PushL(packetRec);
                    packetRec->SetRecordId(iIapRec->iService);
            	    packetRec->LoadL(*iDbs);
            	    iUmtsR99QoSAndOnRecId = packetRec->iUmtsR99QoSAndOnTable;
            	    CleanupStack::PopAndDestroy(packetRec);
        	        }
        	    recordId = iUmtsR99QoSAndOnRecId;
    	        }
    	    break;

    	default:
    		User::Leave(KErrNotFound);
    		}
        }

	if (recordId != -1)
	    {
    	aElement->SetRecordId(recordId);
	    }
	else
	    {
	    User::Leave(KErrNotFound);
	    }
	}

TInt CCommsDatIapView::ConvertBearerTypeToTableId(const TDesC& aBearerType, TMDBElementId& aElementId)
    {
    if (aBearerType.Compare(TPtrC(KCDTypeNameModemBearer)) == 0)
        {
   	    aElementId = KCDTIdModemBearerRecord;
   	    return KErrNone;
        }
    else
    if (aBearerType.Compare(TPtrC(KCDTypeNameLANBearer)) == 0)
	    {
        aElementId = KCDTIdLANBearerRecord;
        return KErrNone;
	    }
	else
    if (aBearerType.Compare(TPtrC(KCDTypeNameVirtualBearer)) == 0)
	    {
    	aElementId = KCDTIdVirtualBearerRecord;
    	return KErrNone;
	    }
	else
	    {
	    return KErrNotFound;
	    }
    }

TInt CCommsDatIapView::ConvertServiceTypeToTableId(const TDesC& aServiceType, TMDBElementId& aElementId)
    {
    if (aServiceType.Compare(TPtrC(KCDTypeNameDialOutISP)) == 0)
        {
        aElementId = KCDTIdDialOutISPRecord;
        return KErrNone;
        }
	else if (aServiceType.Compare(TPtrC(KCDTypeNameDialInISP)) == 0)
        {
	    aElementId = KCDTIdDialInISPRecord;
        return KErrNone;
        }
	else if (aServiceType.Compare(TPtrC(KCDTypeNameLANService)) == 0)
        {
	    aElementId = KCDTIdLANServiceRecord;
        return KErrNone;
        }
	else if (aServiceType.Compare(TPtrC(KCDTypeNameVPNService)) == 0)
        {
	    aElementId = KCDTIdVPNServiceRecord;
        return KErrNone;
        }
    else if (aServiceType.Compare(TPtrC(KCDTypeNameOutgoingWCDMA)) == 0)
        {
	    aElementId = KCDTIdOutgoingGprsRecord;
        return KErrNone;
        }
    else if (aServiceType.Compare(TPtrC(KCDTypeNameIncomingWCDMA)) == 0)
        {
	    aElementId = KCDTIdIncomingGprsRecord;
        return KErrNone;
        }

	return KErrNotFound;
    }

void CCommsDatIapView::IntFieldTypeCheckL(TInt aElementId)
	{
	CommsDat::TCDFieldValueTypes commsdat_type = static_cast<CommsDat::TCDFieldValueTypes>(
									CommsDat::CommsDatSchemaV1_1::GetFieldTypeInfoL(aElementId));

	if (CommsDat::EUint32 != commsdat_type &&
		CommsDat::EInt != commsdat_type &&
		CommsDat::ELink != (commsdat_type & CommsDat::ELink))
		{
		User::Leave(KErrBadName);
		}
	}

void CCommsDatIapView::BoolFieldTypeCheckL(TInt aElementId)
	{
	CommsDat::TCDFieldValueTypes commsdat_type = static_cast<CommsDat::TCDFieldValueTypes>(
									CommsDat::CommsDatSchemaV1_1::GetFieldTypeInfoL(aElementId));

	if (CommsDat::EBool != commsdat_type)
		{
		User::Leave(KErrBadName);
		}
	}

void CCommsDatIapView::TextOrBinFieldTypeCheckL(TInt aElementId)
	{
	CommsDat::TCDFieldValueTypes commsdat_type = static_cast<CommsDat::TCDFieldValueTypes>(
									CommsDat::CommsDatSchemaV1_1::GetFieldTypeInfoL(aElementId));

	if (CommsDat::EText != commsdat_type &&
		CommsDat::EMedText != commsdat_type &&
		CommsDat::ELongText != commsdat_type &&
		CommsDat::EDesC8 != commsdat_type)
		{
		User::Leave(KErrBadName);
		}
	}


