commsfwtools/preparedefaultcommsdatabase/src/CommsDatValidator.cpp
changeset 0 dfb7c4ff071f
child 2 dee179edb159
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commsfwtools/preparedefaultcommsdatabase/src/CommsDatValidator.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,2382 @@
+// Copyright (c) 2004-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:
+// Validation rules for some comms database elements
+// MAINTENANCE - Some rules may need adding or amending whenever the database schema changes
+// No need to validate every entry  
+// Mostly rely on compliance from writers as they are well trusted
+// FILE CONTENTS :
+// 1/  CCDValidator Base class implementation
+// 2/  Validator classes for particular records
+// a) CCDValidatorProxyRecord
+// b) CCDValidatorLANServiceRecord
+// c) CCDValidatorTierRecord
+// d) CCDValidatorConnPref
+// e) CCDValidatorIAPRecord
+// All data in file
+// 
+//
+
+/**
+ @file CommsDatValidator.cpp
+ @internalComponent
+*/
+
+
+#include "CommsDatInternalDefs.h"
+#include <commsdattypesv1_1.h>
+#include "CommsDatValidator.h"
+#include <comms-infras/commsdatschema.h>
+#include <commsdat.h>
+#include "CommsDatMapperAndValidatorUtils.h"
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <commsdattypesv1_1_partner.h>
+#include <commsdat_partner.h>
+#endif
+
+using namespace Meta;
+using namespace CommsDatInternal;
+using namespace CommsDat;
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+//anonymous namespace
+namespace
+    {
+    const TInt KNumServiceType = 12;
+    
+    struct TMapBearerToServiceType
+    	{
+    	TCommDbBearer				bearerMask;
+    	TCommDbConnectionDirection	direction;
+    	const TText*				serviceType;
+    	};
+    
+    const TMapBearerToServiceType KMap[KNumServiceType] =
+    	{
+        	{KCommDbBearerCSD,		ECommDbConnectionDirectionOutgoing, DIAL_OUT_ISP},
+        	{KCommDbBearerCSD,		ECommDbConnectionDirectionIncoming, DIAL_IN_ISP},
+        	{KCommDbBearerWcdma,	ECommDbConnectionDirectionOutgoing, OUTGOING_GPRS},
+        	 /** The following two mappings are only required for tornado */
+        	{KCommDbBearerWcdma,	ECommDbConnectionDirectionIncoming, INCOMING_GPRS},
+        	{KCommDbBearerLAN,		ECommDbConnectionDirectionIncoming,	LAN_SERVICE},
+        	{KCommDbBearerLAN,		ECommDbConnectionDirectionOutgoing,	LAN_SERVICE},
+        	{KCommDbBearerVirtual,	ECommDbConnectionDirectionIncoming,	VPN_SERVICE},
+        	{KCommDbBearerVirtual,	ECommDbConnectionDirectionOutgoing,	VPN_SERVICE},
+        	/** PAN profile uses LAN service table, plus an extension service table */
+        	{KCommDbBearerPAN,		ECommDbConnectionDirectionIncoming,	LAN_SERVICE},
+        	{KCommDbBearerPAN,		ECommDbConnectionDirectionOutgoing,	LAN_SERVICE},
+        	/** WLAN uses LAN service table, plus an extension service table */
+        	{KCommDbBearerWLAN,		ECommDbConnectionDirectionIncoming,	LAN_SERVICE},
+        	{KCommDbBearerWLAN,		ECommDbConnectionDirectionOutgoing,	LAN_SERVICE}
+    	};
+        
+        //this function returns the index in the array of the service type which should be used based
+        //on the received bearer and direction parameters.
+        //it returns KErrNotFound if the service type cannot be found based on the received params.
+        TInt GetIAPServiceType(TUint32& aServTypeArrayStartIndex, TCommDbBearer aBearerSet, TCommDbConnectionDirection aDirection)
+            {
+            for (int i = aServTypeArrayStartIndex; i < KNumServiceType; i++)
+        		{
+        		if ((aBearerSet & KMap[i].bearerMask) != 0 &&
+        			(aDirection == KMap[i].direction ||
+        			 aDirection == ECommDbConnectionDirectionUnknown ))
+        			{
+        			aServTypeArrayStartIndex = i;
+        			return i;
+        			}
+                }
+            return KErrNotFound;
+            }
+        
+        CMDBRecordLink<CCDAccessPointRecord>* GetTheAPxLinkFromAPPrioritySelPol(CCDAPPrioritySelectionPolicyRecord* aAPSelPolRec,
+                                                                        TInt aRankingFromConnPref)
+            {
+            TMetaVTableIterator attribIter(aAPSelPolRec);
+            SVDataTableEntry const* entry = 0;
+            TInt fieldCounter(15);
+            TInt linkNumber(aRankingFromConnPref);
+            CMDBRecordLink<CCDAccessPointRecord>* apPrioritySelPolLink = NULL;
+            
+            while ( (entry = attribIter++) != NULL &&
+                    linkNumber-- > 0 && 
+                    fieldCounter-- > 0 )
+                {
+                apPrioritySelPolLink = reinterpret_cast<CMDBRecordLink<CCDAccessPointRecord>*>(aAPSelPolRec->GetAttribPtr(entry->iOffset));
+                }
+            
+            return apPrioritySelPolLink;
+            }
+    }
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+
+/****************************************************************************************
+ * 1/ CCDValidator   Base class implementaion
+ ****************************************************************************************/
+
+CCDValidator::CCDValidator(CMDBElement* aElement,CMDBSessionImpl& aSession):
+iElement(aElement),iSession(aSession)
+/*
+@internalComponent
+*/
+    {
+    iSession.iMapping = ETrue;
+    }
+
+CCDValidator::~CCDValidator()
+/*
+@internalComponent
+*/
+    {
+    iSession.iMapping = EFalse;
+    }
+            
+
+void CCDValidator::ValidateL(CMDBElement* aElement,CMDBSessionImpl& aSession
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+                             ,TOperation aValidatorOperation
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+                             )
+/*
+Creates a validation object of the appropriate type
+if there are validation rules for aElement
+and calls validate
+
+@internalComponent
+*/
+	{
+	
+    if( aSession.iMapping )
+        {
+        return;
+        }
+
+    if( CommsDat::CommsDatSchema::IsTable(aElement->ElementId()) )
+    	{
+        return;
+        }
+    
+    // then create a validator for the business data if there are any rules set
+    CCDValidator* validator = NULL;
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY        
+    if (EModify == aValidatorOperation ||
+    	EStore == aValidatorOperation)
+    //this is the original behaviour of this method
+        {
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+        if (! CommsDat::CommsDatSchema::IsNode(aElement->ElementId()))
+            {
+            // First validate the field type (see CommsDatSchema)
+            CommsDatSchema::ValidateFieldTypeL(aSession.iOwner, *aElement); 
+            
+            /* Only compliant processes can write to the database
+            
+              don't see it is valuable to validate every field*/
+
+            //return;  
+            }
+
+        switch(aElement->ElementId() & KCDMaskShowRecordType) 
+    		{
+            case KCDTIdConnectionPrefsRecord:
+                {
+                validator = new(ELeave)CCDValidatorConnPref(aElement,aSession
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+                , aValidatorOperation
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+                ); 
+                break;
+                }
+
+            case KCDTIdIAPRecord:
+    		    {
+                validator = new(ELeave)CCDValidatorIAPRecord(aElement,aSession
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+                , aValidatorOperation
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+                ); 
+                break;
+                }
+
+            case KCDTIdLANServiceRecord:
+    		    {
+    			validator = new(ELeave)CCDValidatorLANServiceRecord(aElement,aSession); 
+    			break;
+    		    }
+
+            case KCDTIdProxiesRecord:
+    		    {
+    			validator = new(ELeave)CCDValidatorProxyRecord(aElement,aSession); 
+    			break;
+    		    }
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+            case KCDTIdTierRecord:
+    		    {
+    			validator = new(ELeave)CCDValidatorTierRecord(aElement,aSession); 
+    			break;
+    		    }
+    		
+    #endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+            
+            default :
+                {
+    			return; // Exit quickly if there's no validator
+                }
+            }
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+        }
+    else
+    //the validator should be created for deleting some other data...
+        {
+        switch(aElement->ElementId() & KCDMaskShowRecordType) 
+    		{
+            case KCDTIdConnectionPrefsRecord:
+                {
+                validator = new(ELeave)CCDValidatorConnPref(aElement,aSession, aValidatorOperation); 
+                break;
+                }
+            case KCDTIdIAPRecord:
+    		    {
+                validator = new(ELeave)CCDValidatorIAPRecord(aElement,aSession, aValidatorOperation); 
+                break;
+    		    }
+            default :
+                {
+    			return; // Exit quickly if there's no validator
+                }
+    		}
+        }
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+
+    CleanupStack::PushL(validator);
+   
+    validator->DoValidateL();
+
+    CleanupStack::PopAndDestroy(validator);
+	}
+
+   
+    
+void CCDValidator::DoValidateL()
+/*
+Default is nothing to validate so return 
+
+@internalComponent
+*/
+    {
+    User::LeaveIfError(1 == 1);
+    }
+    
+
+void CCDValidator::OnDeleteL()
+/*
+Default is nothing to delete;
+
+@internalTechnology
+*/
+    {
+    User::LeaveIfError(1 == 1);
+    }
+
+
+
+
+
+/***************************************************************************************    
+ * 2/ VALIDATION CLASSES FOR INDIVIDUAL RECORDS
+ **************************************************************************************/
+
+
+
+/************************* 2a) Validate Proxy Record ************************************
+Validate open link to service record
+*/
+void CCDValidatorProxyRecord::SetShadowElementL()
+	{
+	iShadowElement = CCDRecordBase::RecordFactoryL(KCDTIdProxiesRecord);
+	iShadowElement->SetRecordId(iElement->RecordId());
+	iShadowElement->LoadL(iSession.iOwner);
+	
+	if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) )
+		{
+		//field validation
+		CMDBElement* shadowFieldPtr = static_cast<CMDBRecordBase*>(iShadowElement)->GetFieldByIdL(iElement->ElementId());
+		
+		if ( KCDTIdRecordName == (iElement->ElementId() & KCDMaskShowFieldType) ||
+			 KCDTIdProxyServiceType == (iElement->ElementId() & KCDMaskShowType) ||
+			 KCDTIdServerName == (iElement->ElementId() & KCDMaskShowType) ||
+			 KCDTIdProtocolName == (iElement->ElementId() & KCDMaskShowType) ||
+			 KCDTIdExceptions == (iElement->ElementId() & KCDMaskShowType) )
+			{
+			CMDBField<TDesC>* nameField = static_cast<CMDBField<TDesC>*>(shadowFieldPtr);
+			CMDBField<TDesC>* origField = static_cast<CMDBField<TDesC>*>(iElement);
+
+			nameField->SetL(*origField);
+			}
+		else		
+			{
+			CMDBField<TInt>* numField = static_cast<CMDBField<TInt>*>(shadowFieldPtr);
+			CMDBField<TInt>* origField = static_cast<CMDBField<TInt>*>(iElement);
+			
+			numField->SetL(*origField);
+			}
+		}
+	
+	iElement = iShadowElement;
+	}
+
+
+void CCDValidatorProxyRecord::DoValidateL()
+/*
+Just validate the linked field
+@internalComponent
+*/
+    {
+    if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()))
+    	{
+    	//field validation
+    	SetShadowElementL(); 
+    	}
+    
+#ifndef SYMBIAN_COMMSDAT_USE_INT_RECORD_LINKS
+    CCDProxiesRecord* proxyRecord = static_cast<CCDProxiesRecord*>(iElement);
+
+    if (! proxyRecord->iService.IsNull() && ! proxyRecord->iServiceType.IsNull())
+        {
+        TMDBElementId serviceTypeId = CommsDatSchemaV1_1::LookupTableId(proxyRecord->iServiceType.GetL());
+        proxyRecord->iService = CommsDatSchema::GetLinkIdL(iSession.iOwner, proxyRecord->iService.ElementId(), proxyRecord->iService.GetL(), serviceTypeId/*, &proxyRecord*/);
+        }
+#endif // SYMBIAN_COMMSDAT_USE_INT_RECORD_LINKS
+    }
+
+
+/************************* 2b) Validate LANService Record ***********************************
+Validate open link to service extension record
+*/
+
+void CCDValidatorLANServiceRecord::SetShadowElementL()
+	{
+	iShadowElement = CCDRecordBase::RecordFactoryL(KCDTIdLANServiceRecord);
+	iShadowElement->SetRecordId(iElement->RecordId());
+	iShadowElement->LoadL(iSession.iOwner);
+	
+	if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) )
+		{
+		//field validation
+		CMDBElement* shadowFieldPtr = static_cast<CMDBRecordBase*>(iShadowElement)->GetFieldByIdL(iElement->ElementId());
+		
+		if ( KCDTIdRecordTag == (iElement->ElementId() & KCDMaskShowFieldType) ||
+			 KCDTIdLANIpAddrFromServer == (iElement->ElementId() & KCDMaskShowType) ||
+			 KCDTIdLANIpDNSAddrFromServer == (iElement->ElementId() & KCDMaskShowType) ||
+			 KCDTIdLANIp6DNSAddrFromServer == (iElement->ElementId() & KCDMaskShowType) ||
+			 KCDTIdLANServiceExtensionTableRecordId == (iElement->ElementId() & KCDMaskShowType) )
+			{
+			CMDBField<TInt>* numField = static_cast<CMDBField<TInt>*>(shadowFieldPtr);
+			CMDBField<TInt>* origField = static_cast<CMDBField<TInt>*>(iElement);
+			
+			numField->SetL(*origField);
+			}
+		else
+			{
+			CMDBField<TDesC>* nameField = static_cast<CMDBField<TDesC>*>(shadowFieldPtr);
+			CMDBField<TDesC>* origField = static_cast<CMDBField<TDesC>*>(iElement);
+			
+			nameField->SetL(*origField);	
+			}
+		}
+	
+	iElement = iShadowElement;
+	}
+
+void CCDValidatorLANServiceRecord::DoValidateL()
+/*
+Just validate the linked field
+@internalComponent
+*/
+	{
+    if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()))
+    	{
+    	//field validation
+    	SetShadowElementL(); 
+    	}
+    
+#ifndef SYMBIAN_COMMSDAT_USE_INT_RECORD_LINKS
+    CCDLANServiceRecord* lanServiceRecord = static_cast<CCDLANServiceRecord*>(iElement);
+
+    if (! lanServiceRecord->iServiceExtensionTableRecordId.IsNull() && ! lanServiceRecord->iServiceExtensionTableName.IsNull())
+        {
+        //this was caught in testing but it is not valid to have a real record without these fields...
+        TMDBElementId serviceExtTypeId = CommsDatSchemaV1_1::LookupTableId(lanServiceRecord->iServiceExtensionTableName.GetL());
+
+        lanServiceRecord->iServiceExtensionTableRecordId = 
+            CommsDatSchema::GetLinkIdL(iSession.iOwner, lanServiceRecord->iServiceExtensionTableRecordId.ElementId(), lanServiceRecord->iServiceExtensionTableRecordId.GetL(), serviceExtTypeId/*, &lanServiceRecord*/);    
+        }
+#endif
+    }
+
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+// because tier record doesn't exist before then
+
+/************************* 2c) Validate Tier Record *************************************
+Tier thread name needs to be short name for Tier thread
+*/
+
+void CCDValidatorTierRecord::SetShadowElementL()
+	{
+	iShadowElement = CCDRecordBase::RecordFactoryL(KCDTIdTierRecord);
+	iShadowElement->SetRecordId(iElement->RecordId());
+	iShadowElement->LoadL(iSession.iOwner);
+	
+	if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) )
+		{
+		//field validation
+		CMDBElement* shadowFieldPtr = static_cast<CMDBRecordBase*>(iShadowElement)->GetFieldByIdL(iElement->ElementId());
+		
+		if ( KCDTIdRecordTag == (iElement->ElementId() & KCDMaskShowFieldType) ||
+			 KCDTIdDefaultAccessPoint == (iElement->ElementId() & KCDMaskShowType) )
+			{
+			CMDBField<TInt>* numField = static_cast<CMDBField<TInt>*>(shadowFieldPtr);
+			CMDBField<TInt>* origField = static_cast<CMDBField<TInt>*>(iElement);
+			
+			numField->SetL(*origField);
+			}
+		else
+			{
+			CMDBField<TDesC>* nameField = static_cast<CMDBField<TDesC>*>(shadowFieldPtr);
+			CMDBField<TDesC>* origField = static_cast<CMDBField<TDesC>*>(iElement);
+			
+			nameField->SetL(*origField);	
+			}
+		}
+	
+	iElement = iShadowElement;
+	}
+
+void CCDValidatorTierRecord::DoValidateL()
+/*
+@internalComponent
+*/	
+    {
+    if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) )
+    	{
+    	//field validation
+    	SetShadowElementL(); 
+    	}
+    
+    CCDTierRecord* tierRec = static_cast<CCDTierRecord*>(iElement);
+	if(static_cast<const TDesC16&>(tierRec->iTierThreadName).Length() > KShortTextLength)
+		{
+        __FLOG_STATIC(KLogComponent, KCDErrLog,
+                            _L("CCDValidatorTierRecord::DoValidateL() - TierThreadName > KShortTextLength chars"));
+		User::Leave(KErrTooBig);
+		}
+    }
+
+
+
+
+/***************** 2d) Validate Connection Preference Record *****************************
+*/
+void CCDValidatorConnPref::SetShadowElementL()
+	{	
+	iShadowElement = CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord);
+	iShadowElement->SetRecordId(iElement->RecordId());
+	iShadowElement->LoadL(iSession.iOwner);
+	
+	if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) )
+		{
+		//field validation
+		CMDBElement* shadowFieldPtr = static_cast<CMDBRecordBase*>(iShadowElement)->GetFieldByIdL(iElement->ElementId());
+		
+	
+		if (KCDTIdRecordName == (iElement->ElementId() & KCDMaskShowFieldType))
+			{
+			CMDBField<TDesC>* nameField = static_cast<CMDBField<TDesC>*>(shadowFieldPtr);
+			CMDBField<TDesC>* origField = static_cast<CMDBField<TDesC>*>(iElement);
+			
+			nameField->SetL(*origField);		
+			}
+		else
+			{
+			//the only reason this cast can be done here is that the connPref record contains only
+			//numerical based fields... (except the name field -> handled above...)
+			CMDBField<TInt>* numField = static_cast<CMDBField<TInt>*>(shadowFieldPtr);
+			CMDBField<TInt>* origField = static_cast<CMDBField<TInt>*>(iElement);
+			
+			if (EDelete == iOperation)
+				{
+				numField->SetL(0);
+				}
+			else
+				{
+				numField->SetL(*origField);
+				}
+				
+			//in the case of the IAP link it has to be checked whether is it
+			//given as a full link or only as a record number
+			if (KCDTIdIAPLink == (iElement->ElementId() & KCDMaskShowType))
+				{
+				if ((*origField & KCDMaskShowType) == KCDMaskShowType)
+					{
+					//the value is only a record id
+					numField->SetL(*origField);
+					}
+				else
+					{
+					//the value is a TMDBElementId. Now only the reocrdId is important -> the
+					//connprefValidator is working only with the recId
+					numField->SetL((*origField & KCDMaskShowRecordId) >> 8);
+					}
+				}
+			}
+		}
+	
+	iElement = iShadowElement;
+	}
+#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+
+void CCDValidatorConnPref::DoValidateL()
+	{
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+	if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) ||
+    	 EDelete == iOperation )
+    	{
+    	// a) field validation -> in this case the validator should load the whole record from the DB
+    	//    mimicing record validation
+    	// b) this is a delete operation where only the record id is set on the record container
+    	//    the validator should load the correct element in order to delete the 399 path
+    	SetShadowElementL(); 
+    	}
+#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+    
+    TBool clearHiddenFlag = EFalse;
+	
+    CCDConnectionPrefsRecord* ptrConnPref = static_cast<CCDConnectionPrefsRecord*>(iElement);
+	
+	TInt rank = ptrConnPref->iRanking;
+	TCommDbConnectionDirection direction = ptrConnPref->iDirection;
+	
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+	if (EDelete != iOperation)
+	{
+#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+		//this kind of validation is needed if there is some other operation than delete...
+	    
+		if(ptrConnPref->iDefaultIAP == 0)
+			{
+			/*
+			Since phones get shipped without any predefined IAPs, when a connpref record
+			is stored with the IAP(iDefaultIAP) not set, CED sets its value to 0.
+			Such records hence should be exempted from validation.
+			[Instead of a 0, the behaviour could have been a negative value to remove ambiguity and also
+			could have been mandatory to set that value in the configuration file as well]		
+			*/
+		//	return; 
+			}
+		/* This test is here returniong KErrNotFound for BC reasons. 
+	    It used to assume that value of iDefaultIAP would always be a straight record id
+	    have now modified it to take account of different link values*/
+	    if( ptrConnPref->iDefaultIAP != 0 &&
+	        ptrConnPref->iDefaultIAP >= KCDMaxRecords )
+	        {
+	        if( (ptrConnPref->iDefaultIAP & KLinkableTag) != 0 ||
+	            (ptrConnPref->iDefaultIAP & KCDMaskShowRecordType ) != KCDTIdIAPRecord )
+	            {
+	            // this can't be a valid IAP record
+	            User::Leave(KErrNotFound);  
+	            }
+	        }
+	
+		if(rank > 2)
+			{
+			User::Leave(KErrOverflow); 
+			}
+	
+		if (direction == ECommDbConnectionDirectionIncoming  &&  rank > 1)
+			{
+			User::Leave(KErrNotSupported);
+			}
+		//Re-setting the hidden flag in the case of a leave??????
+	    clearHiddenFlag = ! iSession.IsSetAttributeMask(ECDHidden);
+	    if (clearHiddenFlag)
+	        {
+	        iSession.SetAttributeMask(ECDHidden);
+	        }
+	
+		//check if a record with the same rank already exists
+		CCDConnectionPrefsRecord* ptrConnprefTestRecord = NULL;
+	    
+	    // secondly check records already in the db.
+	
+	    ptrConnprefTestRecord = static_cast<CCDConnectionPrefsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord));
+		CleanupStack::PushL(ptrConnprefTestRecord);
+	 
+	    ptrConnprefTestRecord->iRanking = rank; 
+		ptrConnprefTestRecord->iDirection = direction; 
+	
+		// conditions does not apply for rank 0
+	   	if (rank > 0 && ptrConnprefTestRecord->FindL(iSession.iOwner))
+			{
+			// Since Validation can occur from ModifyL as well, only leave if this isn't the same record
+			if (ptrConnprefTestRecord->RecordId() != ptrConnPref->RecordId() &&
+	            ptrConnprefTestRecord->RecordId() != KCDDefaultRecord)
+				{
+			    User::Leave(KErrAlreadyExists);
+				}
+			}
+		CleanupStack::PopAndDestroy(ptrConnprefTestRecord);
+	
+	    // Check the IAP record id.  look first in cache then in repository
+	    if (ptrConnPref->iDefaultIAP != 0)
+	        {
+	        TInt boo = ptrConnPref->iDialogPref;
+	    	TCommDbDialogPref dialogpref = (TCommDbDialogPref)boo;//TODO change the templated type def of this field;
+	        
+	
+	    	if ( (*(ptrConnPref->iDefaultIAP.Data()) & KCDChangedFlag) == KCDChangedFlag ||
+	    		 (*(ptrConnPref->iBearerSet.Data()) & KCDChangedFlag) == KCDChangedFlag ) 
+	            {
+	            CMDBField<TDesC>* iapServiceType = new(ELeave) CMDBField<TDesC>(KCDTIdIAPServiceType);
+	    		CleanupStack::PushL(iapServiceType);
+	            iapServiceType->SetMaxLengthL(KMaxTextLength);
+	            iapServiceType->SetRecordId(ptrConnPref->iDefaultIAP);    
+	            iapServiceType->LoadL(iSession.iOwner); 
+	            TPtrC serviceType(*iapServiceType);
+	        
+	        	ValidateBearerAndDirectionL(serviceType, ptrConnPref->iDirection, ptrConnPref->iBearerSet, dialogpref);		
+	    		CleanupStack::PopAndDestroy(iapServiceType);
+	            }
+	        }
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+    	}
+#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+    
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+    if ( (ECommDbConnectionDirectionIncoming	!= direction &&		//  -|
+          rank > 0 &&												//   | -> related to sore, modify
+          !iSession.UsingLatestVersion()) )							//   | -> related to the latest session
+        {
+	    IPProtoAPGenerationOrModificationL();
+        }
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+    
+    if (clearHiddenFlag)
+        {
+        iSession.ClearAttributeMask(ECDHidden);
+        }
+    }
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+CCDAPPrioritySelectionPolicyRecord* CCDValidatorConnPref::FindTheAPPrioritySelPolRecL(TInt aReferredIAPRecId)
+    {
+    //CCDConnectionPrefsRecord* ptrConnPref = static_cast<CCDConnectionPrefsRecord*>(&iElement);
+    
+    CCDAPPrioritySelectionPolicyRecord* defAPSelPolRec = NULL;
+    
+    //1st step - Search for the AP which has its tagID with the same value as the 
+    //           recordNumber in the iDefaultIAP field in the ConnPref record or the calculated IAP number. 
+    //           This AP will be the AP on the Link layer.
+    
+    //           This is a checking too to be sure that the AP is existing.
+    CMDBField<TInt>* linkLayerAPTagIDField = new(ELeave) CMDBField<TInt>(KCDTIdAccessPointRecord | KCDTIdRecordTag);
+    *linkLayerAPTagIDField = aReferredIAPRecId;
+    CleanupStack::PushL(linkLayerAPTagIDField);
+        
+    if (EDelete == iOperation ||
+        linkLayerAPTagIDField->FindL(iSession.iOwner))
+        {
+        //2nd step - Search for the default Tier in the GlobalSettings Record 
+        //           (The Global Settings record has to be stored before inserting 
+        //           the ConnectionPreferences record!!!!).
+        CMDBRecordLink<CCDTierRecord>* defaultTierField = new(ELeave) CMDBRecordLink<CCDTierRecord>(KCDTIdGlobalSettingsRecord | KCDTIdDefaultTier);
+        defaultTierField->SetRecordId(1);
+        CleanupStack::PushL(defaultTierField);
+        
+        //this field HAS to be in the GlobalSettings table as we are in 399 config...
+        defaultTierField->LoadL(iSession.iOwner);
+        
+        //3rd step - Follow the defaultAccessPoint link in the defaultTier record which points to
+        //           the default AP record on the Network level.
+        TInt recId = (*defaultTierField) << 8;
+        CMDBRecordLink<CCDAccessPointRecord>* networkDefAPField = 
+                        new(ELeave) CMDBRecordLink<CCDAccessPointRecord>(recId |
+                                                                         KCDTIdDefaultAccessPoint);
+        CleanupStack::PushL(networkDefAPField);
+        
+        networkDefAPField->LoadL(iSession.iOwner);
+        
+        //4th step - Follow the link from the default AP record to the linked APPrioritySelPol record.
+        CMDBRecordLink<CCDAPPrioritySelectionPolicyRecord>* networkSelPolField = 
+                        new(ELeave) CMDBRecordLink<CCDAPPrioritySelectionPolicyRecord>(((*networkDefAPField) & KCDMaskShowRecordId) |
+                                                                                       KCDTIdSelectionPolicy);
+        CleanupStack::PushL(networkSelPolField);
+        
+        networkSelPolField->LoadL(iSession.iOwner);
+        
+        //at this point we already know the complete elementId of the default APPrioritySelPol record.
+        //Read the whole record because it will be needed by the IPProto AP generation logic...
+        
+        defAPSelPolRec = static_cast<CCDAPPrioritySelectionPolicyRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdApPrioritySelectionPolicyRecord));
+                        
+        CleanupStack::PushL(defAPSelPolRec);
+        
+        defAPSelPolRec->SetElementId(*networkSelPolField);
+        defAPSelPolRec->LoadL(iSession.iOwner);
+        
+        //we will transfer the ownership of this object to the IPProtoGenerator object
+        CleanupStack::Pop(defAPSelPolRec);
+        CleanupStack::PopAndDestroy(networkSelPolField);
+        CleanupStack::PopAndDestroy(networkDefAPField);
+        CleanupStack::PopAndDestroy(defaultTierField);
+        }
+    else
+    //The link layer AP is not existing. Leaving...
+        {
+        User::Leave(KErrNotFound);
+        }
+    
+    CleanupStack::PopAndDestroy(linkLayerAPTagIDField);
+    
+    return defAPSelPolRec;
+    }
+
+
+void CCDValidatorConnPref::IPProtoAPGenerationOrModificationL()
+    {
+    CCDConnectionPrefsRecord* ptrConnPref = static_cast<CCDConnectionPrefsRecord*>(iElement);
+    
+    TInt referredIAPRecId = 0;
+    
+    if (EModify == iOperation ||
+    	EStore == iOperation)
+        {
+        if (!(ptrConnPref->iDefaultIAP))
+        /* There is no default IAP in the ConnPref record so this means that 
+         * there is no default legacy path in the DB.
+         *  
+         * - If the connpref record is prompting:
+         * 	 Insert an ipproto AP with a cprconfig field which contains the
+         *   full TMDBElementID of the given connpref record
+         * 
+         * - If the connpref record is not prompting:
+         * 	- If the rank1 record is the record which has the 0 as the IAP field 
+         *    then:
+         * 		- if there is IAP in the DB:
+         * 			a default IAP has to be calculated
+         * 		- if there isn't any IAP rec:
+         * 			- if there is any default ipproto AP:
+         * 				the Default ipproto AP should be used here as the 399 path.
+         * 			- if there isn't any default ipproto AP:
+         * 				one should be generated and linked
+         * 
+         * 	- If the rank2 record is modified like this then:
+         * 		- if there is IAP in the DB:
+         * 			a default IAP has to calculated
+         * 		- if there isn't any IAP rec:
+         * 			nothing can be done...
+         */ 
+            {
+            if (1 == ptrConnPref->iRanking)
+            	{
+            	if (CommsDatMapperAndValidator::IsIAPRecInDB(iSession.iOwner))
+            		{
+            	    //there is IAP in the DB - > we can calculate a default one...
+            		referredIAPRecId = FindIAPWithoutDefIAPL();
+            	    }
+            	else
+            		{
+            		//there is no IAP in the DB
+		            CCDAPPrioritySelectionPolicyRecord* defAPSelPolRec = CommsDatMapperAndValidator::FindTheAPPrioritySelPolRecL(iSession.iOwner);
+		            
+		            CleanupStack::PushL(defAPSelPolRec);
+		            
+		            //Check whether the AP<ranking from the ConnPref rec> is already filled or not.
+		            
+		            // - If it's already filled this means that the IPProto level AP is already existing and
+		            //   needs to be modified only.
+		            
+		            // - If it's not existing yet this means that a new one has to be generated and all the links
+		            //   from or to the new record have to maintained.
+		            CMDBRecordLink<CCDAccessPointRecord>* apPrioritySelPolLink = 
+		                                                GetTheAPxLinkFromAPPrioritySelPol(defAPSelPolRec,
+		                                                                                  ptrConnPref->iRanking);
+		            
+		            __ASSERT_DEBUG(apPrioritySelPolLink, User::Panic(KCommsDatName,EWrongAPPrioritySelPolRecord));
+		            if (!apPrioritySelPolLink)
+		                {
+		                User::Leave(KErrArgument);
+		                }
+		            
+		            CCDAccessPointRecord* defIPProtoAP = NULL;
+		            
+		            if (CommsDatMapperAndValidator::IsDefIPProtoAPInDB(iSession.iOwner))
+		            	{
+		            	//there is an AP with the customSelPol field CCDAccessPointRecord::KNoPolicy. Use that record.
+		            	defIPProtoAP = CommsDatMapperAndValidator::GetTheDefIPProtoAP(iSession.iOwner);
+		            	CleanupStack::PushL(defIPProtoAP);	            	
+		            	}
+		            else
+		            	{
+		            	//there isn't any default ipproto AP -> have to generate one
+		            	defIPProtoAP = CommsDatMapperAndValidator::GenerateIPProtoAPL(IPProtoBaseTagId,
+		    		                                                               	  CCDAccessPointRecord::KNoPolicy,
+		    		                                                               	  iSession.iOwner);
+		    	    	
+		    		    CleanupStack::PushL(defIPProtoAP);
+		    		    
+		    		    defIPProtoAP->iRecordName.SetMaxLengthL(KDefaultIPProtoRecName().Length());
+		    		    defIPProtoAP->iRecordName = KDefaultIPProtoRecName;
+		    		    
+		    		    //save the generated AP record
+		    		    defIPProtoAP->StoreL(iSession.iOwner);
+		            	}
+		            
+	        	    TMDBElementId elemId = defIPProtoAP->ElementId();
+	        	    elemId &= KCDMaskHideAttrAndRes;
+	        	    TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId;
+	        	    elemId &= tableAndRecordBitMask;
+	        	    
+	        	    //update the APPrioritySelPol record to point to the default IPProto AP record
+	        	    CommsDatMapperAndValidator::ModifyAPPrioritySelPolRecL(apPrioritySelPolLink, 
+	        	    													   defAPSelPolRec,
+	        	                                                           elemId);
+	            	
+	        	    defAPSelPolRec->ModifyL(iSession.iOwner);
+	        	    
+	        	    //modify the ipproto tier
+	    		    CMDBRecordLink<CCDAccessPointRecord>* ipProtoDefAccessPoint = new(ELeave)CMDBRecordLink<CCDAccessPointRecord>(KCDTIdDefaultAccessPoint);
+	    		    CleanupStack::PushL(ipProtoDefAccessPoint);
+	    		    
+	    		    TInt ipProtoRecId = CommsDatMapperAndValidator::GetIPProtoTierRecordIdL(iSession.iOwner);
+	    		    ipProtoDefAccessPoint->SetRecordId(ipProtoRecId);
+	    		    
+	    		    *ipProtoDefAccessPoint = elemId;
+	    		    ipProtoDefAccessPoint->ModifyL(iSession.iOwner);
+		            
+	    		    if (KCDChangedFlag == (ptrConnPref->iDialogPref.ElementId() & KCDChangedFlag))
+	    		    	{
+	    		    	/* The dialogPref field has changed -> This means that:
+	    		    	 *  a) we have to create a 'prompting AP' which means that the AP has to 
+	    		    	 *     contain the full TMDBElement ID of the given connpref record in its' 
+	    		    	 *     CprConfig field (prompting connpref rec).
+	    		    	 *  b) the CprConfig field has to contain the IAP record number this 
+	    		    	 *     IPProto AP points to (not prompting connpref rec).
+	    		    	 */ 
+	    		        TBool isPromptingAPNeeded;
+	    		        
+	    		        if (ECommDbDialogPrefUnknown    == ptrConnPref->iDialogPref ||
+	    		            ECommDbDialogPrefDoNotPrompt== ptrConnPref->iDialogPref)
+	    		            {
+	    		            isPromptingAPNeeded = EFalse;
+	    		            }
+	    		        else
+	    		            {
+	    		            isPromptingAPNeeded = ETrue;
+	    		            }
+	    		    	
+	    		        if (isPromptingAPNeeded)
+	    		        	{
+	    		        	//the cprConfig has to contain the full TMDBElementId of the connpref record
+	    		        	defIPProtoAP->iCprConfig = ptrConnPref->ElementId();
+	    		        	}
+	    		        else
+	    		        	{
+	    		        	/* the cprConfig field has to contain the IAP record id
+	    		        	 * Because this mapping/validation is done from a legacy configuration
+	    		        	 * commsdat can assume here that there will be only 3 layers.
+	    		        	 * 
+	    		        	 * The following line says that the IAP pointed by the cprConfig and the
+	    		        	 * Link level AP pointed by the customSelectionPolicy field are the same.
+	    		        	 */
+	    		        	defIPProtoAP->iCprConfig.SetL(ptrConnPref->iDefaultIAP);
+	    		        	}
+	    		        
+	    		        defIPProtoAP->ModifyL(iSession.iOwner);
+	    		    	}
+	    		    
+	    		    CleanupStack::PopAndDestroy(ipProtoDefAccessPoint);
+		            CleanupStack::PopAndDestroy(defIPProtoAP);
+		            CleanupStack::PopAndDestroy(defAPSelPolRec);
+		            
+		            return;
+            		}
+            	}
+            else
+            	{
+            	//rank2 record is modified
+            	if (CommsDatMapperAndValidator::IsIAPRecInDB(iSession.iOwner))
+            		{
+            		//there is IAP in the DB - > we can calculate a default one...
+            		referredIAPRecId = FindIAPWithoutDefIAPL();
+            		}
+            	else
+            		{
+            		/* - there is no IAP in the DB
+            		 * - somebody is inserting a ranking2 connpref record
+            		 * 
+            		 * Is this a normal case????? How should we handle it?
+            		 */
+            		return;
+            		}
+            	}
+            }
+        else
+        //There is a default IAP in the record so just read it...
+        //NOTE that this piece of code here assumes that the IAP in the ConnPref record is only a 
+        //     number and _NOT_ a fully qualified link!!!
+            {
+            referredIAPRecId = ptrConnPref->iDefaultIAP.GetL();
+            }
+        }    
+    
+    //1st step - Search for the AP which has its tagID with the same value as the 
+    //           recordNumber in the iDefaultIAP field in the ConnPref record or the calculated IAP number. 
+    //           This AP will be the AP on the Link layer.
+    
+    //           This is a checking too to be sure that the AP is existing.
+    CMDBField<TInt>* linkLayerAPTagIDField = new(ELeave) CMDBField<TInt>(KCDTIdAccessPointRecord | KCDTIdRecordTag);
+    *linkLayerAPTagIDField = referredIAPRecId;
+    CleanupStack::PushL(linkLayerAPTagIDField);
+    
+    TBool foundLinkLayerAP = linkLayerAPTagIDField->FindL(iSession.iOwner);
+    
+    if (EDelete == iOperation ||
+    	foundLinkLayerAP )
+        {
+        //CCDAPPrioritySelectionPolicyRecord* defAPSelPolRec = FindTheAPPrioritySelPolRecL(referredIAPRecId);
+        
+        CCDAPPrioritySelectionPolicyRecord* defAPSelPolRec = CommsDatMapperAndValidator::FindTheAPPrioritySelPolRecL(iSession.iOwner);
+        
+        CleanupStack::PushL(defAPSelPolRec);
+        
+        //Check whether the AP<ranking from the ConnPref rec> is already filled or not.
+        
+        // - If it's already filled this means that the IPProto level AP is already existing and
+        //   needs to be modified only.
+        
+        // - If it's not existing yet this means that a new one has to be generated and all the links
+        //   from or to the new record have to maintained.
+        CMDBRecordLink<CCDAccessPointRecord>* apPrioritySelPolLink = 
+                                            GetTheAPxLinkFromAPPrioritySelPol(defAPSelPolRec,
+                                                                              ptrConnPref->iRanking);
+        
+        __ASSERT_DEBUG(apPrioritySelPolLink, User::Panic(KCommsDatName,EWrongAPPrioritySelPolRecord));
+        if (!apPrioritySelPolLink)
+            {
+            User::Leave(KErrArgument);
+            }
+        
+        if (*apPrioritySelPolLink)
+        //the AP<x> field has been already filled so the IPProto level AP is already existing. Only 
+        //modification is needed.
+            {
+            if (EModify == iOperation ||
+            	EStore == iOperation)
+                {
+                iIPProtoGenerator = new(ELeave) CIPProtoAPModifier(defAPSelPolRec,
+                                                                   *iElement,  
+                                                                   iSession,
+                                                                   referredIAPRecId);
+                
+                //we transferred the ownership of this object to the IPProtoGenerator object
+                CleanupStack::Pop(defAPSelPolRec);
+                }
+            else
+            //The pointed AP should be deleted...
+                {
+                iIPProtoGenerator = new(ELeave) CIPProtoAPRemover(defAPSelPolRec,
+                                                                  *iElement,  
+                                                                  iSession);
+                
+                //we transferred the ownership of this object to the IPProtoGenerator object
+                CleanupStack::Pop(defAPSelPolRec);
+                }
+            }
+        else
+        //the AP<x> field has not been filled yet so creation is needed.
+            {
+            if (EModify == iOperation ||
+            	EStore == iOperation)
+                {
+                iIPProtoGenerator = new(ELeave) CIPProtoAPCreator(defAPSelPolRec,
+                                                                  *iElement,  
+                                                                  iSession,
+                                                                  referredIAPRecId);
+                
+                //we transferred the ownership of this object to the IPProtoGenerator object
+                CleanupStack::Pop(defAPSelPolRec);
+                }
+            else
+            //hm... This is a delete operation and the AP<x> field is not filled in the
+            //APPrioritySelPol record. Database is inconsistent - would be better to leave??
+                {
+                CleanupStack::PopAndDestroy(defAPSelPolRec);
+                CleanupStack::PopAndDestroy(linkLayerAPTagIDField);
+                return;
+                }
+            }
+        
+        //Modify or generate the IPProto level AP.
+        iIPProtoGenerator->DoTheWorkL();
+        }
+    else
+    //The link layer AP is not existing. Leaving...
+        {
+        User::Leave(KErrNotFound);
+        }
+    
+    CleanupStack::PopAndDestroy(linkLayerAPTagIDField);
+    }
+    
+
+/**
+NOTE: This function is a modified copy from the void CCommsDbTableView::ConstructL(TUint32 aBearerSet,	TCommDbConnectionDirection aDirection)
+      function (in the commdb/commdbshim/scdb/cdbtable.cpp)!!
+*/
+TInt CCDValidatorConnPref::FindIAPWithoutDefIAPL()
+	{
+    CCDConnectionPrefsRecord* ptrConnPref = static_cast<CCDConnectionPrefsRecord*>(iElement);
+    
+	CCDIAPRecord* iapRecord = static_cast<CCDIAPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord));
+	CleanupStack::PushL(iapRecord);
+	
+    CMDBField<TCommDbConnectionDirection>& direction = ptrConnPref->iDirection;
+	CMDBField<TUint32>& bearerSet = ptrConnPref->iBearerSet;
+	
+	TUint32 tempBearer = static_cast<TUint32>(bearerSet);
+	TCommDbConnectionDirection tempDirection = static_cast<TCommDbConnectionDirection>(direction);
+	
+	TBool defIAPFound = EFalse;
+	
+    TUint32 servTypeArrayStartIndex = 0;
+	
+    while ((!defIAPFound) && ((TInt)servTypeArrayStartIndex < KNumServiceType))
+    	{
+	    TInt serviceTypeIndex = GetIAPServiceType( servTypeArrayStartIndex, (TCommDbBearer)tempBearer, tempDirection );
+	    __ASSERT_DEBUG(serviceTypeIndex!=KErrNotFound, User::Panic(KCommsDatName,EWrongIAPServiceType));
+	    if (KErrNotFound == serviceTypeIndex)
+	        {
+	        User::LeaveIfError(serviceTypeIndex);
+	        }
+	    
+		const TPtrC serviceType(KMap[serviceTypeIndex].serviceType);
+		
+		// prime the service type
+		iapRecord->iServiceType.SetMaxLengthL(serviceType.Length());
+		iapRecord->iServiceType = serviceType;
+		
+		defIAPFound = iapRecord->FindL(iSession.iOwner);
+		if (!defIAPFound)
+		    {
+		    //No IAP record can be found with the given service
+		    ++servTypeArrayStartIndex;
+		    }
+    	}
+	
+	if (!defIAPFound)
+	    {
+	    //No IAP record can be found with the given service(s)
+	    User::Leave(KErrNotFound);
+	    }
+	
+	
+	TInt tempRecId = iapRecord->RecordId();
+	
+	CleanupStack::PopAndDestroy(iapRecord);
+	
+    return tempRecId;
+	}
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+
+void CCDValidatorConnPref::ValidateBearerAndDirectionL(const TDesC& aServiceType, TCommDbConnectionDirection aDirection, TUint32 aBearerSet, TCommDbDialogPref aDlgPref)
+	{
+	TCommDbConnectionDirection expectedDirection = ECommDbConnectionDirectionUnknown;
+	TInt expectedBearer = KCommDbBearerUnknown;
+
+	if (aServiceType == TPtrC(DIAL_OUT_ISP))
+		{
+		expectedDirection = ECommDbConnectionDirectionOutgoing;
+		expectedBearer = KCommDbBearerCSD;
+		}
+	else if (aServiceType == TPtrC(DIAL_IN_ISP))
+		{
+		expectedDirection = ECommDbConnectionDirectionIncoming;
+		expectedBearer = KCommDbBearerCSD;
+		}
+	else if (aServiceType == TPtrC(OUTGOING_GPRS))
+		{
+		expectedDirection = ECommDbConnectionDirectionOutgoing;
+		expectedBearer = KCommDbBearerWcdma;
+		}
+	else if (aServiceType == TPtrC(INCOMING_GPRS))
+		{
+		expectedDirection = ECommDbConnectionDirectionIncoming;
+		expectedBearer = KCommDbBearerWcdma;
+		}
+	else if (aServiceType == TPtrC(LAN_SERVICE))
+		{
+		expectedBearer = KCommDbBearerLAN | KCommDbBearerPAN | KCommDbBearerWLAN;
+		}
+	else if (aServiceType == TPtrC(VPN_SERVICE))
+		{
+		expectedBearer = KCommDbBearerVirtual;
+		}
+	
+	TBool valid;
+	if (aDlgPref == ECommDbDialogPrefPromptIfWrongMode)
+		{
+		// this pref should only be used for PSD bearers
+		// if expectedBearer == KCommDbBearerWcdma then bearer set should
+		// include something other than KCommDbBearerWcdma
+		valid = (~expectedBearer & aBearerSet) != 0 && (expectedBearer == KCommDbBearerWcdma);
+		}
+	else if (aDlgPref == ECommDbDialogPrefPrompt)
+		{
+		// the expected bearer should be included in the bearer set
+		// along with any other bearer
+
+		if (aServiceType == TPtrC(VPN_SERVICE))	
+			valid = ETrue;
+		else
+			valid = (expectedBearer & aBearerSet) != 0;
+		}
+	else
+		{
+		// no restriction on the dialog preference
+		valid = ETrue;
+		}
+
+	if (valid)
+		{
+		valid = aDirection == expectedDirection ||
+			expectedDirection == ECommDbConnectionDirectionUnknown;
+		}
+
+	if (!valid)
+		User::Leave(KErrArgument);
+	}
+
+
+
+/************************ 2e) Validate IAP Record ************************************
+*/
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+
+	
+// The relation of an IAP to its mapped AccessPoint records is as depicted below:
+//
+//  IAP table (index == RecordId)               AP table (index == Tag)
+//  ---------                                   --------
+//
+//                                              
+//   -----                  iCprConfig == 1 (a)  -----
+//  |    1|<------------------------------------|    1|
+//  |     |- - - - - - - - - - - - - - - - - - >|     |<----------- +  
+//   -----         (inferred association)        -----              |
+//    ^ |                                   link AP                 |
+//    | |                                                           |
+//    | |                                                           |
+//    | |                                                           |
+//    | |                                                           |
+//    | |                                                           |
+//    | |   iAccessPoint == 256 (b)               -----             |
+//    | +-------------------------------------->|  256| iSelectionPolicy == 257 (c)
+//    |                                         |     |----+        |
+//    |                                          -----     |        |
+//    |                                     net AP         |        |
+//    |                                                    |        |
+//    |                     iCprConfig == 1 (a)  -----     |        |
+//    +-----------------------------------------|  257|<---+        |
+//                                              |     |-------------+ 
+//                                               -----  iSelectionPolicy == 1 (d)
+//                                          ipProto AP
+//
+//
+// The following expressions are used to link the IAP and AP records:
+// where:
+// n = IAP record's recordId.
+// B = the LinkBoundary (reserved Tags, currently 255)
+//
+// (a) = n
+// (b) = B + 2n - 1
+// (c) = (b) + 1
+// (d) = n 
+//
+
+// The first 'KAPToIAPMappingThreshold' Tag Ids ('B' in the diagram above) are reserved for direct IAP to AP mapping,
+// for those AP records where the index must match that of the RecordId of the corresponding IAP record.
+//
+// Note:
+// We put the mapped AP's at the top of the permissible recordIds (being 254) and grows downwards.
+//
+// This should avoid colliding with any user created (either via input file, or dynamically). 
+// At time of writing, in the XML files, the RecordId cannot be specified (unlike in .cfg files) and a record's Id 
+// is calculated on the basis of its order of declaration in its table (in the markup).
+// 
+// In .cfg files (where it is able and usual to specify the recordId - using the well known "# COMMDB_ID = x" 
+// statements) it is usual to start from 1 and count upwards.
+//
+// This might change, so is not included in the check at top of the function, when finding mapped AP records.
+//
+//static const TUint KAPToIAPTagMappingThreshold     = 255;
+static const TUint KAPToIAPRecordIdMappingConstant = 251;
+
+// TCleanupOperation function.
+//
+template <class T>
+void DestroyRPointerArray(TAny* aPtr)
+    {
+    RPointerArray<T>* self = static_cast<RPointerArray<T>*>(aPtr);
+    self->ResetAndDestroy();
+    }
+
+
+static const TUint32 KZero = 0;
+    
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+void CCDValidatorIAPRecord::DeleteAssociatedLinkLevelAPL()
+	{
+	CCDAccessPointRecord* linkAPRecord = static_cast<CCDAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord));
+	CleanupStack::PushL(linkAPRecord);
+	
+	linkAPRecord->iRecordTag = iElement->RecordId();
+	
+	if (linkAPRecord->FindL(iSession.iOwner))
+		{
+		linkAPRecord->DeleteL(iSession.iOwner);
+		}
+	
+	CleanupStack::PopAndDestroy(linkAPRecord);
+	}
+#endif
+
+void CCDValidatorIAPRecord::ServiceAndBearerValidationL()
+	{
+#ifndef SYMBIAN_COMMSDAT_USE_INT_RECORD_LINKS
+	//at this point iElement has to be an IAP record!!!
+	CCDIAPRecord* iapRecord = static_cast<CCDIAPRecord*>(iElement);
+	
+    if (!iapRecord->iService.IsNull() && !iapRecord->iServiceType.IsNull())
+        {
+        //this was caught in testing but actually it is not valid to have a real record without these fields...
+        
+        TMDBElementId tableTypeId = CommsDatSchemaV1_1::LookupTableId(iapRecord->iServiceType.GetL());
+        iapRecord->iService = CommsDatSchema::GetLinkIdL(iSession.iOwner, iapRecord->iService.ElementId(), iapRecord->iService.GetL(), tableTypeId/*, &iapRecord*/);
+        }
+
+    if (!iapRecord->iBearer.IsNull() && !iapRecord->iBearerType.IsNull())
+        {
+        //this was caught in testing but actually it is not valid to have a real record without these fields...
+        
+        TMDBElementId tableTypeId = CommsDatSchemaV1_1::LookupTableId(iapRecord->iBearerType.GetL());
+        iapRecord->iBearer = CommsDatSchema::GetLinkIdL(iSession.iOwner, iapRecord->iBearer.ElementId(), iapRecord->iBearer.GetL(), tableTypeId/*, &iapRecord*/);
+        }
+#endif
+	}
+
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+void CCDValidatorIAPRecord::AssociatedLinkLevelAPGenerationL()
+	{
+    
+    // map to AP record
+	
+	//at this point iElement has to be an IAP record!!!
+    CCDIAPRecord* iapRecord = static_cast<CCDIAPRecord*>(iElement);
+    
+    /*
+    some of this work is a bit like mapping, but 
+    the IAP record is still present in the database so doing this as validation
+    */
+    TInt err = KErrNone;
+        
+    //typedef enum {ENetworkAP, EIPProtocolAP, ELinkAP, EAPRecordIndicesLast = ELinkAP, EAPRecordIndicesRange = EAPRecordIndicesLast + 1} TAPRecordIndices;
+
+    // Calculate the 3 potential AP indices
+    //
+	const TInt KThisIAPRecordId = iapRecord->RecordId();
+	const TInt KLinkAPTag       = KThisIAPRecordId;
+	//const TInt KNetworkAPTag    = KAPToIAPTagMappingThreshold + (2 * KThisIAPRecordId) - 1;
+	//const TInt KIPProtoAPTag    = KNetworkAPTag + 1;
+
+    __FLOG_STATIC1(KLogComponent, KCDInfoLog,
+                        _L("CCDValidatorIAPRecord::DoValidateL() - Processing IAP record <%d>"),
+                        KThisIAPRecordId);
+
+
+    // 666
+    // Should tidy these variables up into a class, but the turgidness of it all is just
+    // distracting from getting immediate objective of getting over-night build tests going.
+    //
+    // Create copies of these recordIds, not so clever.
+    //
+    
+    //const TInt  KAPRecordIdsTable[]    = {KNetworkAPTag, KIPProtoAPTag, KLinkAPTag};
+    TUint numberOfAPRecordsFound = 0;
+          
+	//RPointerArray<CCDAccessPointRecord> apRecords;
+    //CleanupStack::PushL(TCleanupItem(DestroyRPointerArray<CCDAccessPointRecord>, &apRecords));
+    
+    TBuf<KCDMaxFieldNameLength> tempName;
+     _LIT(KMappedFrom, "MappedFromIAP");
+
+   // See which, if any of the records of interest exist already.
+    //
+    //for (TUint i = 0; i <= EAPRecordIndicesLast; i++)
+     //   {
+    	CCDAccessPointRecord* record = static_cast<CCDAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord));
+	    CleanupStack::PushL(record);
+	    //apRecords.InsertL(record, i);
+	    
+        // Prime the search record and load it.
+
+        TBool found = EFalse;        
+        record->iRecordTag = KLinkAPTag; //KAPRecordIdsTable[i];
+        TRAPD(loadErr, found = record->FindL(iSession.iOwner));           
+        
+        // Apply additional rules when validating, a mapped IAP must conform to.
+        //
+        if (loadErr == KErrNone && found)
+            {
+            _LIT(KAPNameCheckFormat, "%S%d");
+            tempName.Format(KAPNameCheckFormat, &KMappedFrom, KThisIAPRecordId);
+
+            // Its name should be that expected (ie which was applied by this function).
+            //
+            TPtrC tempPtr(static_cast<const TDesC&>(record->iRecordName));
+            if (tempPtr.Find(tempName) != KErrNotFound
+            	&& record->iSelectionPolicy == 0)
+
+            // And the selection policy and cpr config should conform to the diagram at the top of this function.
+            //
+                 {
+           	    numberOfAPRecordsFound++;
+                 }
+            }
+        if (loadErr != KErrNone && loadErr != KErrNotFound)
+            {
+        	CleanupStack::PopAndDestroy(record);
+        	record = NULL;
+    		User::Leave(loadErr);
+            }
+       // } // for...
+	
+
+    // Now let's evaluate what we've found.
+    //    
+    if (numberOfAPRecordsFound == 0)
+        {
+        __FLOG_STATIC1(KLogComponent, KCDInfoLog,
+                            _L("CCDValidatorIAPRecord::DoValidateL() - Creating AP record for IAP record <%d>"),
+                                    KThisIAPRecordId);
+
+        // No AP records exist for this IAP, the IAP record therefore needs to be mapped.
+            
+        // Go on and create the 3 new AP records... neatly presented from top to bottom of stack.
+        
+        _LIT(KAPNameFormat, "%S%S%d");
+
+
+   	    CCDAccessPointRecord *newAPRecord =
+   	                static_cast<CCDAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord));
+		CleanupStack::PushL(newAPRecord);
+
+	    const TInt KBaseAPRecordId = KAPToIAPRecordIdMappingConstant - KThisIAPRecordId;
+
+        // ... and finally the link record
+
+        // The clean up stack handling of 'pBearerType' seems a bit contorted.
+        
+        CCDBearerTypeRecord* pBearerType = NULL;
+        TRAPD(ret, pBearerType = NewBearerTypeRecordL(iSession.iOwner, *iapRecord));
+        if (ret != KErrNone || !pBearerType)
+            {
+            // Unfortunately, there are incorrect/unused IAPs in some of these configuration files (presumably they're dead).
+            //
+            __FLOG_STATIC1(KLogComponent, KCDInfoLog,
+                                _L("CCDValidatorIAPRecord::DoValidateL() - error when mapping IAP record %d to its bearer"),
+                                        KThisIAPRecordId);
+
+            if (pBearerType)
+                {
+        		CleanupStack::PushL(pBearerType);
+                }
+                
+            // But since we're not aiming to validate their config files, don't flag error, otherwise we'll leave and
+            // the user will never get to create a (to them) usable database.
+            }
+        else if (ret == KErrNone && pBearerType)
+            {
+    		CleanupStack::PushL(pBearerType);
+
+           	TPtrC name(pBearerType->iRecordName);
+            tempName.Format(KAPNameFormat, &name, &KMappedFrom, KThisIAPRecordId);
+            InitialiseAccessPointRecordL(
+                *newAPRecord,
+                tempName,
+                KBaseAPRecordId - KThisIAPRecordId,
+                KLinkAPTag,
+                pBearerType->iTier,
+                pBearerType->iMCpr,
+                KZero,
+                pBearerType->iCpr,
+                KZero,
+                pBearerType->iSCpr,
+                pBearerType->iProtocol);
+            newAPRecord->StoreL(iSession.iOwner);        // 666 - TRAP
+
+			TInt linkAPTagId = newAPRecord->iRecordTag;
+			
+			if (!CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(linkAPTagId, iSession.iOwner))
+				   {
+				   //The IPProto AP is not existing yet. Generate one.
+				   CCDAccessPointRecord* ipprotoAP = CommsDatMapperAndValidator::GenerateIPProtoAPL(IPProtoBaseTagId, linkAPTagId, iSession.iOwner);
+				   CleanupStack::PushL(ipprotoAP);
+	    
+				   //save the generated AP record
+				   ipprotoAP->StoreL(iSession.iOwner);
+				   CleanupStack::PopAndDestroy(ipprotoAP);
+				   }
+
+            
+            __FLOG_STATIC1(KLogComponent, KCDInfoLog,
+                                _L("CCDValidatorIAPRecord::DoValidateL() - Created AP records for IAP record <%d>"),
+                                        KThisIAPRecordId);
+        
+    		// Update the IAP record itself to point to top-most AP tier record.
+    		//
+    		//thisIAPRecord->iAccessPoint = KNetworkAPTag;
+    	    }
+    	else
+    	    {
+            // 666 All 1 expected AP records exist and the links between records make sense.
+            // So we assume that they have been correctly mapped already - perhaps have been called from ModifyL()?
+            // Do nothing
+            //
+            __FLOG_STATIC1(KLogComponent, KCDInfoLog,
+                                _L("CCDValidatorIAPRecord::DoValidateL() - Found existing valid AP record for IAP record <%d>"),
+                                        KThisIAPRecordId);
+    	    }
+
+
+        if (pBearerType)    	    
+            {
+    	    CleanupStack::PopAndDestroy(pBearerType);
+    	    }
+		CleanupStack::PopAndDestroy(newAPRecord);
+        }
+
+	CleanupStack::PopAndDestroy(record);
+	
+	if (err != KErrNone)
+	    {
+		//User::Leave(err);
+        __FLOG_STATIC2(KLogComponent, KCDErrLog,
+              _L("CCDValidatorIAPRecord::DoValidateL() - error <%d> when mapping IAP record <%d> to AP - indeterminate state"),
+              err, KThisIAPRecordId);
+	    }
+
+	}
+#endif
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+void CCDValidatorIAPRecord::SetShadowElementL()
+	{
+	iShadowElement = CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord);
+	iShadowElement->SetRecordId(iElement->RecordId());
+	iShadowElement->LoadL(iSession.iOwner);
+	
+	if ( KCDMaskShowFieldType != (KCDMaskShowFieldType & iElement->ElementId()) )
+		{
+		//field validation
+		CMDBElement* shadowFieldPtr = static_cast<CMDBRecordBase*>(iShadowElement)->GetFieldByIdL(iElement->ElementId());
+		
+	
+		if ( KCDTIdRecordName == (iElement->ElementId() & KCDMaskShowFieldType) ||
+			 KCDTIdIAPServiceType == (iElement->ElementId() & KCDMaskShowType) ||
+			 KCDTIdIAPBearerType == (iElement->ElementId() & KCDMaskShowType) )
+			{
+			CMDBField<TDesC>* nameField = static_cast<CMDBField<TDesC>*>(shadowFieldPtr);
+			CMDBField<TDesC>* origField = static_cast<CMDBField<TDesC>*>(iElement);
+			
+			nameField->SetL(*origField);		
+			}
+		else
+			{
+			//the only reason this cast can be done here is that the iap record contains only
+			//numerical based fields... (except the name, bearertype, servicetype fields -> handled above...)
+			CMDBField<TInt>* numField = static_cast<CMDBField<TInt>*>(shadowFieldPtr);
+			CMDBField<TInt>* origField = static_cast<CMDBField<TInt>*>(iElement);
+			
+			if (EDelete == iOperation)
+				{
+				numField->SetL(0);
+				}
+			else
+				{
+				numField->SetL(*origField);
+				}
+			}
+		}
+	
+	iElement = iShadowElement;
+	}
+#endif
+
+void CCDValidatorIAPRecord::DoValidateL()
+/*
+ 1/ Validate the record links for service and bearer records
+ ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+ 2/ Create an AP record etc
+ endif SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+
+@internalComponent
+*/
+    {
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+	if (EDelete == iOperation )
+    	{
+	    if ( KCDMaskShowFieldType == (KCDMaskShowFieldType & iElement->ElementId()) )
+	    	{
+	    	//deleting a whole IAP record -> the associated AP record should be deleted as well
+	    	DeleteAssociatedLinkLevelAPL();
+	    	}
+	    else
+	    	{
+	    	//deleting only a field from the record. Here the validator checks the inegrity of the IAP record.
+	    	//So if the client deleted one of the bearer or service fields the integrity check won't be successful
+	    	//we have to copy the origElemId because the SetShadowElementL will reset it...
+	    	TUint origElemId = iElement->ElementId();
+	    	
+	    	SetShadowElementL();
+	    	ServiceAndBearerValidationL();
+	    	
+	    	if ( KCDTIdIAPAppSid == (origElemId & KCDMaskShowType) )
+	    		{
+	    		//this field has to be mapped to the associated AP
+	    		CMDBField<TInt>* linkAPTagId = new(ELeave)CMDBField<TInt>(KCDTIdAccessPointRecord | KCDTIdRecordTag);
+	    		CleanupStack::PushL(linkAPTagId);
+	    		
+	    		*linkAPTagId = iElement->RecordId();
+	    		if (linkAPTagId->FindL(iSession.iOwner))
+	    			{
+		    		CMDBField<TInt>* appSidField = new(ELeave)CMDBField<TInt>(KCDTIdAppSID);
+		    		CleanupStack::PushL(appSidField);
+		    		
+		    		appSidField->SetRecordId(linkAPTagId->RecordId());
+		    		appSidField->DeleteL(iSession.iOwner);
+	    			
+		    		CleanupStack::PopAndDestroy(appSidField);
+	    			}
+	    		CleanupStack::PopAndDestroy(linkAPTagId);
+	    		}
+	    	}
+    	}
+    else if (EStore == iOperation ||
+    		 EModify == iOperation )
+    	{
+    	if ( KCDMaskShowFieldType == (KCDMaskShowFieldType & iElement->ElementId()) )
+    		{
+    		//ModifyL or StoreL is called on a record container
+    		ServiceAndBearerValidationL();
+    		}
+    	else
+    		{
+    		//it's a field modification
+    		SetShadowElementL();
+    		ServiceAndBearerValidationL();
+    		}
+    	
+    	if (EModify == iOperation)
+    		{
+    		DeleteAssociatedLinkLevelAPL();
+    		}
+    	
+    	AssociatedLinkLevelAPGenerationL();
+    	}
+#else
+    ServiceAndBearerValidationL();
+#endif
+    } // CCDMapperIAPRecord::DoValidateL()
+
+
+void CCDValidatorIAPRecord::OnDeleteL()
+    {
+    // TODO Cleanup on deletion of IAP record (cleanup matching AP?) 
+    // meanwhile do nothing
+    User::LeaveIfError(ETrue); 
+    }
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+void CCDValidatorIAPRecord::InitialiseAccessPointRecordL(      CCDAccessPointRecord& lhs,
+                                                      const TDesC&                aRecordName,
+                                                            TInt                  aRecordId,
+                                                            TInt                  aTag,
+                                                            TUint32               aTier,
+                                                            TUint32               aMCpr,
+                                                            TUint32               aSelectionPolicy,
+                                                            TUint32               aCpr,
+                                                            TUint32               aCprConfig,
+                                                            TUint32               aSCpr,
+                                                            TUint32               aProtocol)
+    {
+    lhs.iRecordName.SetMaxLengthL(aRecordName.Length());
+	lhs.iRecordName      = aRecordName;
+	lhs.SetRecordId(aRecordId);
+    lhs.iRecordTag       = aTag;
+	lhs.iTier            = aTier;
+	lhs.iMCpr            = aMCpr;
+	lhs.iSelectionPolicy = aSelectionPolicy;
+	lhs.iCpr             = aCpr;
+	lhs.iCprConfig       = aCprConfig;
+	lhs.iSCpr            = aSCpr;
+    lhs.iProtocol        = aProtocol;
+    
+    CCDIAPRecord* iapRecord = static_cast<CCDIAPRecord*>(iElement);
+    
+	lhs.iAppSID.SetL(iapRecord->iAppSid);
+	lhs.iPriority        = KMaxTUint;
+    }
+#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+CCDBearerTypeRecord* CCDValidatorIAPRecord::NewBearerTypeRecordL(CMDBSession& aSessionOwner, CCDIAPRecord& aIAPRecord)
+    {
+    typedef enum {EModemBearer, ELANBearer, EVirtualBearer, TBearersLast = EVirtualBearer} TBearers;
+
+    CCDBearerTypeRecord* pBearerType = NULL;
+    
+    __FLOG_STATIC1(KLogComponent, KCDInfoLog,
+                        _L("CCDValidatorIAPRecord::NewBearerTypeRecordL() - Searching for bearer-type for IAP <%d>"),
+                                aIAPRecord.RecordId());
+
+    // Note:
+    // These constants and tables are all grouped together at the top of the function.
+    //
+    // When intelligent links are added to CommsDat, much of this, and associated code, should become redundant.
+    
+    // Lookup table of the relevant bearer string identifiers.
+    // Keys for the IAP record's 'iBearerType' field.
+    //
+    const TText* const KBearerLookupTable[] =
+        {
+        KCDTypeNameModemBearer,
+        KCDTypeNameLANBearer,
+        KCDTypeNameVirtualBearer
+        };
+
+    // Lookup table of the relevant TMDBElementIds
+    //
+    const TMDBElementId KBearerIdLookupTable[] =
+        {
+        KCDTIdModemBearerRecord,
+        KCDTIdLANBearerRecord,
+        KCDTIdVirtualBearerRecord
+        };
+
+    _LIT(KSpudNif,       "spud");
+    _LIT(KSpudNifPrefix, "spud-%S");
+    _LIT(KOutgoingGPRS,  "outgoinggprs");
+    _LIT(KLowerNifKey,   "lowernif=");
+
+
+    TBearers thisBearer = EModemBearer;
+    TBool    found      = EFalse;
+ 	if (!aIAPRecord.iBearerType.IsNull())
+   	    {
+       	TPtrC bearerType(aIAPRecord.iBearerType);
+       	
+       	for (TInt i = 0; i <= TBearersLast; i++)
+       	    {
+       	    if (bearerType.CompareF(TPtrC(KBearerLookupTable[i])) == 0)
+       	        {
+       	        thisBearer = static_cast<TBearers>(i);
+                __FLOG_STATIC1(KLogComponent, KCDInfoLog,
+                                    _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - Found bearer-type <%d>"),
+                                            thisBearer);
+                found = ETrue;
+       	        break;
+       	        }
+       	    }
+       	}
+
+
+    if (!found)
+        {
+        return pBearerType;
+        }
+        
+
+    CCDBearerRecordBase* pBearer = static_cast<CCDBearerRecordBase*>(CCDRecordBase::RecordFactoryL(KBearerIdLookupTable[thisBearer]));
+    CleanupStack::PushL(pBearer);
+    
+    __FLOG_STATIC2(KLogComponent, KCDInfoLog,
+                        _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - Loading bearer record <%d>, for bearer-type <%d>"),
+                                static_cast<TInt>(aIAPRecord.iBearer),
+                                thisBearer);
+
+    pBearer->SetRecordId(aIAPRecord.iBearer);
+    pBearer->LoadL(aSessionOwner);
+    
+
+   	pBearerType = static_cast<CCDBearerTypeRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdBearerTypeRecord));
+	CleanupStack::PushL(pBearerType);
+
+
+    TBool keepGoing = ETrue;
+    
+    TBuf<KMaxName> thisNifName;
+
+    // Get the bearer's nif name (shouldn't the NifName be a member of the base class?, oh well, too late now).
+    // Requires horrible switch statement.
+    //
+    switch (thisBearer)
+        {
+        case EModemBearer:
+            {
+            // The usual modem bearer case is:
+            //
+            //      ModemBearer[IAP.iBearer]->iNifName
+            //
+            // SPUD is an exception (if ModemBearer[IAP.iBearer]->iNifName == "SPUD"):
+            //
+            //      OutgoingGPRS[IAP.Service]->iIfParame
+            //          Extract the nif's name from the resultant string, of form "lowernif=xxxxx"
+            
+
+            TPtrC nifName(static_cast<CCDModemBearerRecord*>(pBearer)->iNifName);
+            
+            if (nifName.CompareF(KSpudNif) == 0)
+                {
+                // Do "special" SPUD related processing to find the lowernif from the OutgoingGPRS table.
+
+               	TPtrC serviceType(aIAPRecord.iServiceType);
+
+                // Check the expected service type
+                //
+           	    if (serviceType.CompareF(KOutgoingGPRS) == 0)
+           	        {
+                    CCDOutgoingGprsRecord* pOutgoingGprs =
+                            static_cast<CCDOutgoingGprsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdOutgoingGprsRecord));
+                    CleanupStack::PushL(pOutgoingGprs);
+
+                    // Load the associated OutgoingGPRS record.
+                    
+                    pOutgoingGprs->SetRecordId(aIAPRecord.iService);
+                    pOutgoingGprs->LoadL(aSessionOwner);
+
+                    // Get the 'iGPRSIfParams' value.
+                     
+            	    TPtrC gprsIfParams(static_cast<CCDOutgoingGprsRecord*>(pOutgoingGprs)->iGPRSIfParams);
+
+                    // And search for the key and its value (which should be the Nif we want)
+                    //            	    
+            	    TInt lowerNifIndex = gprsIfParams.FindF(KLowerNifKey);
+            	    if (lowerNifIndex >= 0)
+            	        {
+            	        TPtrC lowerNifName = gprsIfParams.Mid(lowerNifIndex + KLowerNifKey().Length());
+ 
+                        // Cannot work out how to use the iRecordName member itself to call Format() on.
+                        
+            	        thisNifName.Format(KSpudNifPrefix, &lowerNifName);
+            	        }
+            	    else
+            	        {
+                        __FLOG_STATIC1(KLogComponent, KCDErrLog,
+                                            _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - Failed to find \"lowernif=\" for IAP record <%d>"),
+                                                    aIAPRecord.RecordId());
+            	        keepGoing = EFalse;
+            	        }
+            	    
+                    CleanupStack::PopAndDestroy(pOutgoingGprs);
+           	        }
+           	    else
+           	        {
+                    __FLOG_STATIC1(KLogComponent, KCDErrLog,
+                                        _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - unexpected SPUD bearer for IAP record <%d>"),
+                                                aIAPRecord.RecordId());
+                    keepGoing = EFalse;
+           	        }
+                }
+            else
+                {
+                // That's easy            
+                thisNifName = nifName;
+                }
+            }
+            break;
+            
+        case ELANBearer:
+            {
+           	TPtrC nifName(static_cast<CCDLANBearerRecord*>(pBearer)->iLanBearerNifName);
+            thisNifName = nifName;
+           	}
+           	break;
+           	
+    	case EVirtualBearer:
+            {
+           	TPtrC nifName(static_cast<CCDVirtualBearerRecord*>(pBearer)->iVirtualBearerNifName);
+            thisNifName = nifName;
+           	}
+           	break;
+
+        default:
+            keepGoing = EFalse;
+            break;
+        }       
+           
+           	    
+    if (keepGoing)
+        {
+        __FLOG_STATIC2(KLogComponent, KCDInfoLog,
+                            _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - Looking up data for bearer-type <%S> for IAP <%d>"),
+                                    &thisNifName,
+                                    aIAPRecord.RecordId());
+
+        // The letters in the name of the bearer can appear in various cases. therefore
+        // convert the name of the bearer (however it was found) to lower-case letters. 
+        //
+        // Note:
+        // Constraint is that the names of the bearer types in the preface file must also be lower-case.
+        //
+        thisNifName.LowerCase();
+        pBearerType->iRecordName.SetMaxLengthL(thisNifName.Length());
+        pBearerType->iRecordName = thisNifName;
+        
+    	if (!pBearerType->FindL(aSessionOwner))
+	        {
+            __FLOG_STATIC2(KLogComponent, KCDErrLog,
+                                _L("CCDMapperIAPRecord::NewBearerTypeRecordL() - Failed to find bearer-type <%S> for IAP <%d>"),
+                                        &thisNifName,
+                                        aIAPRecord.RecordId());
+
+			User::Leave(KErrNotFound);
+	        }
+        }
+
+    CleanupStack::Pop(pBearerType);
+    CleanupStack::PopAndDestroy(pBearer);
+        
+    return pBearerType;
+    } // NewBearerTypeRecordL()
+
+#endif // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+
+
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+
+
+
+//---------- The IPProto AP handler classes -------------
+    
+/*virtual*/ void CIPProtoAPCreator::DoTheWorkL()
+    {
+    CCDConnectionPrefsRecord* ptrConnPref = static_cast<CCDConnectionPrefsRecord*>(&iElement);
+    
+    CMDBRecordLink<CCDAccessPointRecord>* apPrioritySelPolFieldToBeModified = 
+                                                GetTheAPxLinkFromAPPrioritySelPol(iAPSelPolRec,
+                                                                                  ptrConnPref->iRanking);
+    CCDAccessPointRecord* ipprotoAP = NULL;
+    
+    TBool modified = EFalse;
+	TBool isIPProtoAPExisting = EFalse;
+	
+    if (ECommDbDialogPrefUnknown    == ptrConnPref->iDialogPref ||
+        ECommDbDialogPrefDoNotPrompt== ptrConnPref->iDialogPref)
+        {
+        //this is a non prompting connpref rec
+        isIPProtoAPExisting = CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(iLinkAPTagId, 
+    															 				   iSession.iOwner);
+        }
+    else
+    	{
+    	//this connpref rec is prompting so we need to consider the cprConfig field of the possibly
+    	//existing IPProtoAP too
+    	isIPProtoAPExisting = CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(iLinkAPTagId, 
+    																			   ptrConnPref->ElementId(), 
+    															 				   iSession.iOwner);
+    	}
+    
+    if (!isIPProtoAPExisting)
+    	{
+    	//The IPProto AP is not existing yet. Generate one.
+	    ipprotoAP = CommsDatMapperAndValidator::GenerateIPProtoAPL(IPProtoBaseTagId,
+	                                                               iLinkAPTagId,
+	                                                               iSession.iOwner);
+	    
+	    CleanupStack::PushL(ipprotoAP);
+	    
+	    ipprotoAP->StoreL(iSession.iOwner);
+	    
+	    //modified = ETrue;
+    	}
+    else
+    	{
+    	//The IPProto AP is already exsiting. Use that one.
+    	ipprotoAP = CommsDatMapperAndValidator::LoadTheAPL(iLinkAPTagId, iSession.iOwner);
+    	
+    	CleanupStack::PushL(ipprotoAP);
+    	}
+    
+    
+    if (KCDChangedFlag == (ptrConnPref->iDialogPref.ElementId() & KCDChangedFlag))
+    	{
+    	/* The dialogPref field has changed -> This means that:
+    	 *  a) we have to create a 'prompting AP' which means that the AP has to 
+    	 *     contain the full TMDBElement ID of the given connpref record in its' 
+    	 *     CprConfig field (prompting connpref rec).
+    	 *  b) the CprConfig field has to contain the IAP record number this 
+    	 *     IPProto AP points to (not prompting connpref rec).
+    	 */ 
+        TBool isPromptingAPNeeded;
+        
+        if (ECommDbDialogPrefUnknown    == ptrConnPref->iDialogPref ||
+            ECommDbDialogPrefDoNotPrompt== ptrConnPref->iDialogPref)
+            {
+            isPromptingAPNeeded = EFalse;
+            }
+        else
+            {
+            isPromptingAPNeeded = ETrue;
+            }
+    	
+        if (isPromptingAPNeeded)
+        	{
+        	//the cprConfig has to contain the full TMDBElementId of the connpref record
+        	ipprotoAP->iCprConfig = ptrConnPref->ElementId();
+        	}
+        else
+        	{
+        	/* the cprConfig field has to contain the IAP record id
+        	 * Because this mapping/validation is done from a legacy configuration
+        	 * commsdat can assume here that there will be only 3 layers.
+        	 * 
+        	 * The fillowing line says that the IAP pointed by the cprConfig and the
+        	 * Link level AP pointed by the customSelectionPolicy field are the same.
+        	 */
+        	ipprotoAP->iCprConfig.SetL(ipprotoAP->iCustomSelectionPolicy);
+        	}
+        
+        modified = ETrue;
+    	}
+    
+    if (modified)
+    	{
+    	ipprotoAP->ModifyL(iSession.iOwner);
+    	}
+    
+    TMDBElementId elemId = ipprotoAP->ElementId();
+    elemId &= KCDMaskHideAttrAndRes;
+    TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId;
+    elemId &= tableAndRecordBitMask;
+    
+    //a) update the APPrioritySelPol record to point to the newly creeated AP record
+    CommsDatMapperAndValidator::ModifyAPPrioritySelPolRecL(apPrioritySelPolFieldToBeModified, 
+                                                          iAPSelPolRec,
+                                                          elemId);
+    
+    
+    iAPSelPolRec->ModifyL(iSession.iOwner);
+    
+    //maintain the link from the IPProto Tier record
+    if (1 == ptrConnPref->iRanking)
+        {
+        CommsDatMapperAndValidator::ModifyDefaultTierRecordL(elemId, iSession.iOwner);
+        }
+    
+    CleanupStack::PopAndDestroy(ipprotoAP);
+    }
+
+
+
+/*virtual*/ void CIPProtoAPModifier::DoTheWorkL()
+    {
+    TBool modified = EFalse;
+    CCDConnectionPrefsRecord* ptrConnPref = static_cast<CCDConnectionPrefsRecord*>(&iElement);
+    
+    CMDBRecordLink<CCDAccessPointRecord>* apPrioritySelPolFieldToBeModified = 
+                                                GetTheAPxLinkFromAPPrioritySelPol(iAPSelPolRec,
+                                                                                  ptrConnPref->iRanking);
+    
+    CCDAccessPointRecord* apRecordToBeModified = NULL;
+    
+    /* At this point we have to check: 
+     * 
+     * Is there any other link to this AP.
+     * If there is: 
+     * ------------  
+     * 		a new AP should be generated and linked from the given
+     * 		APPrioritySelPol field
+     * 
+     * If there isn't:
+     * --------------- 
+     * 		Is there any other IPProto AP which contains the given link AP tagId
+     * 		in its' customSelPolField?
+     * 			If there is:
+     * 				No new AP should be generated but the already existing one
+     * 				should be used
+     * 				The AP which is not used anymore should be deleted
+     * 
+     * 			If there isn't
+     * 				this means that the given AP can be modified.
+     */
+    if (1 == CommsDatMapperAndValidator::CountReferenceToThisIPProtoAPL(*apPrioritySelPolFieldToBeModified,
+    																	iSession.iOwner))
+    	{
+    	/* There is only 1 reference to this AP. Here the following should be considered:
+    	 * If there is already an IPProto AP whith the given link AP tagId value in the customselPol field
+    	 * no new AP should be generated but the one should be used, and the old one should be deleted!.
+    	 * If there is no AP with the given link AP tagId value in the customselPol field
+    	 * a new one should be generated.
+    	 */
+    	
+    	if (!CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(iLinkAPTagId, iSession.iOwner))
+    		{
+    		//ok, there is no AP with the given customSelPol field
+	        apRecordToBeModified = static_cast<CCDAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord));
+	        CleanupStack::PushL(apRecordToBeModified);
+	        
+	        apRecordToBeModified->SetElementId(*apPrioritySelPolFieldToBeModified);
+	        
+	    	apRecordToBeModified->LoadL(iSession.iOwner);
+    		}
+    	else
+    		{
+    		//there is already an AP with the given customSelPol field
+    		//delete the currently used IPProto AP
+    		apRecordToBeModified = CommsDatMapperAndValidator::LoadTheAPL(iLinkAPTagId, iSession.iOwner);
+        	
+        	CleanupStack::PushL(apRecordToBeModified);
+        	
+    		CCDAccessPointRecord* apRecordToBeDeleted = static_cast<CCDAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord));
+    		CleanupStack::PushL(apRecordToBeDeleted);
+    		//DeleteL needs the '7F' in the FieldType...
+    		apRecordToBeDeleted->SetElementId(*apPrioritySelPolFieldToBeModified | KCDMaskShowFieldType);
+    		
+        	if (apRecordToBeDeleted->RecordId() != apRecordToBeModified->RecordId())
+        		{
+        		//we can delete the actual AP...
+	        	apRecordToBeDeleted->DeleteL(iSession.iOwner);
+	        	
+	    	    TMDBElementId elemId = apRecordToBeModified->ElementId();
+	    	    elemId &= KCDMaskHideAttrAndRes;
+	    	    TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId;
+	    	    elemId &= tableAndRecordBitMask;
+	    	    
+	    	    //update the APPrioritySelPol record to point to the newly creeated AP record
+	    	    CommsDatMapperAndValidator::ModifyAPPrioritySelPolRecL(apPrioritySelPolFieldToBeModified, 
+	    	                                                          iAPSelPolRec,
+	    	                                                          elemId);
+        		}
+        	
+        	CleanupStack::PopAndDestroy(apRecordToBeDeleted);
+        	
+    		}
+    	}
+    else
+    	{
+    	/* There is more than 1 link to the given AP record. 
+    	 * If we would modify it with the same Link level TagId -> no necessary to do anything...
+    	 * 		This could happen if we processed already the IAPPrioritySelPol record and there
+    	 * 		is a ConnPref record too where the default IAP is the same as in the orig
+    	 * 		IAPPriorioritySelPol record. 
+    	 * If it's a different Link level TagId -> Can't modify the AP instead create a new one.
+    	 */
+    	
+    	TBool isIPProtoAPExisting = EFalse;
+    	
+        if (ECommDbDialogPrefUnknown    == ptrConnPref->iDialogPref ||
+            ECommDbDialogPrefDoNotPrompt== ptrConnPref->iDialogPref)
+            {
+            //this is a non prompting connpref rec
+            isIPProtoAPExisting = CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(iLinkAPTagId, 
+        															 				   iSession.iOwner);
+            }
+        else
+        	{
+        	//this connpref rec is prompting so we need to consider the cprConfig field of the possibly
+        	//existing IPProtoAP too
+        	isIPProtoAPExisting = CommsDatMapperAndValidator::IsIPProtoAPAlreadyExistL(iLinkAPTagId, 
+        																			   ptrConnPref->ElementId(), 
+        															 				   iSession.iOwner);
+        	}
+        
+    	if (isIPProtoAPExisting)
+    		{
+    		//the given IPProto is already existing with the received Link TagId (and cprConfig
+    		//field if the connpref is prompting). Let's use that one
+    		apRecordToBeModified = CommsDatMapperAndValidator::LoadTheAPL(iLinkAPTagId, iSession.iOwner);
+        	
+        	CleanupStack::PushL(apRecordToBeModified);
+    		
+    		}
+    	else
+    		{
+	    	apRecordToBeModified = CommsDatMapperAndValidator::GenerateIPProtoAPL(IPProtoBaseTagId,
+		                                                               			  iLinkAPTagId,
+		                                                               			  iSession.iOwner);
+	    	
+		    CleanupStack::PushL(apRecordToBeModified);
+		    
+		    //save the generated AP record
+		    apRecordToBeModified->StoreL(iSession.iOwner);
+    		}
+		    
+	    TMDBElementId elemId = apRecordToBeModified->ElementId();
+	    elemId &= KCDMaskHideAttrAndRes;
+	    TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId;
+	    elemId &= tableAndRecordBitMask;
+	    
+	    //update the APPrioritySelPol record to point to the newly creeated AP record
+	    CommsDatMapperAndValidator::ModifyAPPrioritySelPolRecL(apPrioritySelPolFieldToBeModified, 
+	                                                          iAPSelPolRec,
+	                                                          elemId);
+    	}
+    
+    if (0 != apRecordToBeModified->iSelectionPolicy)
+    //it is possible from the cfg files that the iSelectionPolicy field is used to link to the 
+    //link layer AP. If this is the case it should be 0ed.
+        {
+        apRecordToBeModified->iSelectionPolicy.SetL(0);
+        modified = ETrue;
+        }
+    
+    if (apRecordToBeModified->iCustomSelectionPolicy != iLinkAPTagId)
+        {
+        apRecordToBeModified->iCustomSelectionPolicy.SetL(iLinkAPTagId);
+        apRecordToBeModified->iCprConfig.SetL(iLinkAPTagId);
+        modified = ETrue;
+        }
+    
+    /* This is just cosmetics here. If we modify the default IPProto AP, which is
+     * coming from the meshpreface, then the name of the record should be modified.
+     */ 
+    TPtrC recName(apRecordToBeModified->iRecordName);
+    if (0 == recName.Compare(KDefaultIPProtoRecName))
+    	{
+        //buffer for the record name
+        TBuf<KMaxName> recordName;
+        CommsDatMapperAndValidator::GenerateRecordName(recordName, apRecordToBeModified->iRecordTag);
+        apRecordToBeModified->iRecordName.SetMaxLengthL(recordName.Length());
+        apRecordToBeModified->iRecordName = recordName;
+        modified = ETrue;
+    	}
+        
+    if (KCDChangedFlag == (ptrConnPref->iDialogPref.ElementId() & KCDChangedFlag))
+    	{
+    	/* The dialogPref field has changed -> This means that:
+    	 *  a) we have to create a 'prompting AP' which means that the AP has to 
+    	 *     contain the full TMDBElement ID of the given connpref record in its' 
+    	 *     CprConfig field (prompting connpref rec).
+    	 *  b) the CprConfig field has to contain the IAP record number this 
+    	 *     IPProto AP points to (not prompting connpref rec).
+    	 */ 
+        TBool isPromptingAPNeeded;
+        
+        if (ECommDbDialogPrefUnknown    == ptrConnPref->iDialogPref ||
+            ECommDbDialogPrefDoNotPrompt== ptrConnPref->iDialogPref)
+            {
+            isPromptingAPNeeded = EFalse;
+            }
+        else
+            {
+            isPromptingAPNeeded = ETrue;
+            }
+    	
+        if (isPromptingAPNeeded)
+        	{
+        	//the cprConfig has to contain the full TMDBElementId of the connpref record
+        	apRecordToBeModified->iCprConfig = ptrConnPref->ElementId();
+        	}
+        else
+        	{
+        	/* the cprConfig field has to contain the IAP record id
+        	 * Because this mapping/validation is done from a legacy configuration
+        	 * commsdat can assume here that there will be only 3 layers.
+        	 * 
+        	 * The following line says that the IAP pointed by the cprConfig and the
+        	 * Link level AP pointed by the customSelectionPolicy field are the same.
+        	 */
+        	apRecordToBeModified->iCprConfig.SetL(apRecordToBeModified->iCustomSelectionPolicy);
+        	}
+        
+        modified = ETrue;
+    	}
+    
+    iAPSelPolRec->ModifyL(iSession.iOwner);
+    
+    if (modified)
+        {
+        apRecordToBeModified->ModifyL(iSession.iOwner);
+        }
+    
+    //maintain the link from the IPProto Tier record
+    if (1 == ptrConnPref->iRanking)
+        {
+	    TMDBElementId elemId = apRecordToBeModified->ElementId();
+	    elemId &= KCDMaskHideAttrAndRes;
+	    TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId;
+	    elemId &= tableAndRecordBitMask;
+	    
+        CommsDatMapperAndValidator::ModifyDefaultTierRecordL(elemId, iSession.iOwner);
+        }
+    
+    
+    
+	/* one last checking: if there is another IPProto AP with the same cusomtSelPol
+	 * and CprConfig fields then only 1 can be in the database the other should be deleted.
+	 */
+    if (CommsDatMapperAndValidator::GetNumberOfThisIPProtoAPL(apRecordToBeModified, iSession.iOwner) > 1)
+    	{
+    	//this means that we have 2 IPProto AP with the same CustomSelPol and CprConfig
+    	//fields
+    	
+    	//Correct the links from the defaultTier and APPriotySelPol links
+    	//This is the elementId which will be deleted
+    	CommsDatMapperAndValidator::CorrectLinksL(apRecordToBeModified->ElementId(), iSession.iOwner);
+    	
+    	//delete the AP
+    	apRecordToBeModified->DeleteL(iSession.iOwner);
+    	}
+    
+    CleanupStack::PopAndDestroy(apRecordToBeModified);
+    }
+
+/*virtual*/ void CIPProtoAPRemover::DoTheWorkL()
+    {
+    CCDConnectionPrefsRecord* ptrConnPref = static_cast<CCDConnectionPrefsRecord*>(&iElement);
+    
+        
+    CMDBRecordLink<CCDAccessPointRecord>* apPrioritySelPolFieldToBeModified = 
+                                                GetTheAPxLinkFromAPPrioritySelPol(iAPSelPolRec,
+                                                                                  ptrConnPref->iRanking);
+    
+    CCDAccessPointRecord* ipprotoAPRec = NULL;
+    
+    
+
+    //if this was a ranking1 AP then the tier record has to be modified too...
+    if (1 == ptrConnPref->iRanking)
+        {
+        /**
+        !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!    IMPORTANT:   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+        
+        The RANK1 connpref record is deleted which means that there is no default legacy path
+        in the database. In the 399 architecture in this case we create the default IPProto AP
+        which is in the meshpreface file by default (it's possible that it's overwritten) so 
+        we modify the current AP by not deleting it but modifying it to contain the CCDAccessPointRecord::KNoPolicy value
+        in its' CustomSelectionPolicy field.
+        
+        !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+        */
+	    if (1 == CommsDatMapperAndValidator::CountReferenceToThisIPProtoAPL(*apPrioritySelPolFieldToBeModified,
+	    																	iSession.iOwner))
+	    	{
+	    	//ok there is only 1 link to this AP -> we can modify it
+	    	
+	    	ipprotoAPRec = static_cast<CCDAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord));
+	    	CleanupStack::PushL(ipprotoAPRec);
+	    	
+	    	ipprotoAPRec->SetRecordId((*apPrioritySelPolFieldToBeModified & KCDMaskShowRecordId) >> 8);
+	    	
+	    	
+	    	ipprotoAPRec->LoadL(iSession.iOwner);
+	        
+	    	ipprotoAPRec->iCustomSelectionPolicy = CCDAccessPointRecord::KNoPolicy;
+	        
+		    ipprotoAPRec->iRecordName.SetMaxLengthL(KDefaultIPProtoRecName().Length());
+		    ipprotoAPRec->iRecordName = KDefaultIPProtoRecName;
+		    
+		    ipprotoAPRec->iCprConfig = 0;
+		    
+	    	ipprotoAPRec->ModifyL(iSession.iOwner);
+	    	}
+	    else
+	    	{
+	    	//a new default AP should be generated
+	    	ipprotoAPRec = CommsDatMapperAndValidator::GenerateIPProtoAPL(IPProtoBaseTagId,
+		                                                               	  CCDAccessPointRecord::KNoPolicy,
+		                                                               	  iSession.iOwner);
+	    	
+		    CleanupStack::PushL(ipprotoAPRec);
+		    
+		    ipprotoAPRec->iRecordName.SetMaxLengthL(KDefaultIPProtoRecName().Length());
+		    ipprotoAPRec->iRecordName = KDefaultIPProtoRecName;
+		    
+		    //save the generated AP record
+		    ipprotoAPRec->StoreL(iSession.iOwner);
+		    
+		    
+		    TMDBElementId elemId = ipprotoAPRec->ElementId();
+		    elemId &= KCDMaskHideAttrAndRes;
+		    TMDBElementId tableAndRecordBitMask = KCDMaskShowRecordType | KCDMaskShowRecordId;
+		    elemId &= tableAndRecordBitMask;
+		    
+		    //update the APPrioritySelPol record to point to the newly creeated AP record
+		    CommsDatMapperAndValidator::ModifyAPPrioritySelPolRecL(apPrioritySelPolFieldToBeModified, 
+		                                                          iAPSelPolRec,
+		                                                          elemId);
+		    
+		    iAPSelPolRec->ModifyL(iSession.iOwner);
+		    
+		    //modify the IPProto tier to point to this new default AP
+		    CMDBRecordLink<CCDAccessPointRecord>* ipProtoDefAccessPoint = new(ELeave)CMDBRecordLink<CCDAccessPointRecord>(KCDTIdDefaultAccessPoint);
+		    CleanupStack::PushL(ipProtoDefAccessPoint);
+		    
+		    TInt ipProtoRecId = CommsDatMapperAndValidator::GetIPProtoTierRecordIdL(iSession.iOwner);
+		    ipProtoDefAccessPoint->SetRecordId(ipProtoRecId);
+		    
+		    *ipProtoDefAccessPoint = elemId;
+		    ipProtoDefAccessPoint->ModifyL(iSession.iOwner);
+	        
+		    CleanupStack::PopAndDestroy(ipProtoDefAccessPoint);
+	    	}
+        //no further modification is needed here...
+        }
+    else
+    	{
+    	//RANK2 record is deleted
+	    iAPSelPolRec->iApCount.SetL(1);
+	    
+	    if (1 == CommsDatMapperAndValidator::CountReferenceToThisIPProtoAPL(*apPrioritySelPolFieldToBeModified,
+	    																	iSession.iOwner))
+	    	{
+	    	//ok, there is only 1 link to this AP -> it can be deleted
+	    	ipprotoAPRec = static_cast<CCDAccessPointRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdAccessPointRecord));
+	    	
+	    	CleanupStack::PushL(ipprotoAPRec);
+	    	
+	    	ipprotoAPRec->SetRecordId((*apPrioritySelPolFieldToBeModified & KCDMaskShowRecordId) >> 8);
+	    	
+	    	ipprotoAPRec->DeleteL(iSession.iOwner);
+	    	}
+	    
+	    //update the APPrioritySelPol record. 
+	    *apPrioritySelPolFieldToBeModified = 0;
+	    iAPSelPolRec->ModifyL(iSession.iOwner);
+    	}
+    
+    if (ipprotoAPRec)
+    	{
+    	CleanupStack::PopAndDestroy(ipprotoAPRec);
+    	}
+    }
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+//EOF