commsfwtools/preparedefaultcommsdatabase/Tools/ced/src/CXMLContentHandler.cpp
changeset 0 dfb7c4ff071f
child 21 07656293a99c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commsfwtools/preparedefaultcommsdatabase/Tools/ced/src/CXMLContentHandler.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,1594 @@
+// Copyright (c) 2003-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:
+//
+
+#include <e32test.h>
+#include <f32file.h>
+#include <stringpool.h>
+#include "dbdef.h"
+#include <xml/documentparameters.h>
+#include <xml/taginfo.h>
+#include <xml/attribute.h>
+#include "CXMLContentHandler.h"
+
+#include "filedump.h"
+extern CFileDump* gMsg;		// logging
+using namespace Xml;
+#ifdef SYMBIAN_NETWORKING_3GPPDEFAULTQOS
+extern TBool gDeprecatedFields;
+#endif
+
+//anonymous namespace
+//These things are needed only here... Don't mess up the global namespace
+namespace
+    {
+    // The names of the tables to modify
+    const TText* const modTable[] =
+    	{
+    	_S("IAPTable"),
+    	_S("IAPTable"),
+    	_S("IAPTable"),
+    	_S("IAPTable"),
+    	_S("IAPTable"),
+
+    	_S("ProxyTable"),
+
+    	_S("WAPIPBearerTable"),
+    	_S("WAPIPBearerTable"),
+
+    	_S("WAPSMSBearerTable"),
+
+    	_S("VpnServiceTable"),
+    	_S("VpnServiceTable"),
+
+    	_S("ConnectionPreferencesTable"),
+
+    	_S("GlobalSettingsTable"),
+    	_S("GlobalSettingsTable"),
+    	_S("GlobalSettingsTable"),
+    	_S("GlobalSettingsTable"),
+    	_S("OutgoingGPRSTable"),
+
+    	_S("WLANServiceExtensionTable"),
+
+    	_S("EAPSecuritySettingsTable"),
+
+    	_S("TunnelledEAPSettingsTable")
+
+    	};
+
+    // The names of the parameters to modify
+    const TText* const modParam[] =
+    	{
+    	// IAPTable
+       _S("IAPService"),
+    	_S("IAPBearer"),
+    	_S("IAPNetwork"),
+    	_S("LocationRef"),
+    	_S("ChargecardRef"),
+    	
+    	// ProxyRef
+    	_S("ISPRef"),
+
+    	// WAPIPBearerTable
+    	_S("AccessPoint"),
+    	_S("IAPRef"),
+
+    	// WAPSMSBearerTable
+    	_S("AccessPoint"),
+
+    	// VpnServiceTable
+    	_S("HomeIAP"),
+    	_S("HomeNetwork"),
+
+    	// ConnectionPreferencesTable
+    	_S("IAPRef"),
+
+    	// GlobalSettingsTable
+    	_S("DefaultNetwork"),
+    	_S("LocationForDataAndFax"),
+    	_S("LocationForPhoneServicesAndSMS"),
+    	_S("WAPAccess"),
+
+    	// OutgoingGPRSTable
+    	_S("UmtsR99QoSAndOnRef"),
+
+    	//WLANServiceExtensionTable
+    	_S("Wlan_Security_Data"),
+
+    	//EAPSecuritySettingsTable
+    	_S("EAP_Method_Data"),
+
+    	//TunnelledEAPSettingsTable
+    	_S("Tun_EAP_Method_Data")
+    	};
+
+    // The new names of the modified parameters
+    const TText* const newModParam[] =
+    	{
+    	// IAPTable
+    	_S("IAPService"),
+    	_S("IAPBearer"),
+    	_S("IAPNetwork"),
+    	_S("Location"),
+    	_S("Chargecard"),
+    	
+    	// ProxyRef
+    	_S("ISP"),
+
+    	// WAPIPBearerTable
+    	_S("AccessPointId"),
+    	_S("IAP"),
+
+       // WAPSMSBearerTable
+    	_S("AccessPointId"),
+
+    	// VpnServiceTable
+    	_S("HomeIAP"),
+    	_S("HomeNetwork"),
+
+    	// ConnectionPreferencesTable
+    	_S("IAP"),
+
+    	// GlobalSettingsTable
+    	_S("DefaultNetwork"),
+    	_S("LocationForDataAndFax"),
+    	_S("LocationForPhoneServicesAndSMS"),
+    	_S("WAPAccessPoint"),
+
+    	// OutgoingGPRSTable
+    	_S("UmtsR99QoSAndOn"),
+
+    	//WLANServiceExtensionTable
+    	_S("Wlan_Security_Data"),
+
+    	//EAPSecuritySettingsTable
+    	_S("EAP_Method_Data"),
+
+    	//TunnelledEAPSettingsTable
+    	_S("Tun_EAP_Method_Data")
+    	};
+
+    /**
+      The names of the new parameters to add which indicate the
+      table where the table entry reference is
+    */
+    const TText* const typeParam[] =
+    	{
+       _S("IAPServiceType"),
+    	_S("IAPBearerType"),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S("ProxyServiceType"),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S(""),
+    	_S("")
+    	};
+
+    const TInt numMods = 20;
+
+    const TText* const noNameTables[] =
+    	{
+       _S("GlobalSettingsTable"),
+    	_S("ProxyTable"),
+    	_S("AgentLookupTable"),
+    	_S("WAPIPBearerTable"),
+    	_S("WAPSMSBearerTable"),
+    	_S("SecureSocketTable"),
+    	_S("BTDefaultTable"),
+    	_S("BTDeviceTable"),
+    	_S("BTPersistTable"),
+    	_S("BTSecurityTable"),
+    	_S("ConnectionPreferencesTable")
+    	};
+
+    const TInt numNoNameTables = 11;
+
+    /**
+     * These two arrays (tableNamesForPairing, tmdbElementsForPairing) are needed because an
+     * RHashMap is built up to handle these pairs. It is needed to serch for the table ID
+     * based on the table name read form the xml config file.
+     */
+
+        const TText* const tableNamesForPairing[] =
+            {
+            _S("NetworkTable"),			        //KCDTIdNetworkRecord
+            _S("IAPTable"),			            //KCDTIdIAPRecord
+            _S("ModemBearerTable"), 	        //KCDTIdModemBearerRecord
+            _S("LANBearerTable"), 		        //KCDTIdLANBearerRecord
+            _S("LANServiceTable"), 		        //KCDTIdLANServiceRecord
+            _S("DialInISPTable"), 		        //KCDTIdDialInISPRecord
+            _S("DialOutISPTable"), 		        //KCDTIdDialOutISPRecord
+            _S("AgentLookupTable"), 		    //KCDTIdAgentLookupRecord
+            _S("ChargecardTable"), 		        //KCDTIdChargecardRecord
+            _S("ConnectionPreferencesTable"), 	//KCDTIdConnectionPrefsRecord
+            _S("GlobalSettingsTable"), 		    //KCDTIdGlobalSettingsRecord
+            _S("IncomingGPRSTable"), 		    //KCDTIdIncomingGprsRecord
+            _S("OutgoingGPRSTable"), 		    //KCDTIdOutgoingGprsRecord
+            //_S("DefaultGPRSTable"), 		    //<NOKIA magic...>
+            _S("ProxyTable"), 			        //KCDTIdProxiesRecord
+            _S("LocationTable"), 		        //KCDTIdLocationRecord
+            _S("SecureSocketTable"), 		    //KCDTIdSSProtoRecord
+            //_S("BTDeviceTable"), 		        //<not used anymore>
+            //_S("BTPersistTable"), 		    //<not used anymore>
+            //_S("BTSecurityTable"), 		    //<not used anymore>
+            //_S("BTDefaultTable"), 		    //<not used anymore>
+            _S("WAPAccessPointTable"), 		    //KCDTIdWAPAccessPointRecord
+            _S("WAPIPBearerTable"), 		    //KCDTIdWAPIPBearerRecord
+            _S("WAPSMSBearerTable"), 		    //KCDTIdWAPSMSBearerRecord
+            _S("VirtualBearerTable"), 		    //KCDTIdVirtualBearerRecord
+            _S("VpnServiceTable"), 		        //KCDTIdVPNServiceRecord
+            _S("WLANServiceExtensionTable"), 	//KCDTIdWLANServiceExtRecord
+            _S("PANServiceExtensionsTable"), 	//KCDTIdPANServiceExtRecord
+            _S("EAPSecuritySettingsTable"), 	//KCDTIdEAPSecRecord
+            _S("TunnelledEAPSettingsTable"), 	//KCDTIdTunEAPRecord
+			_S("EAPTLSSettingsTable"), 		    //KCDTIdEAPTLSRecord
+#ifndef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+			_S("LEAPSettingsTable") 		    //KCDTIdLEAPRecord
+#else
+			_S("LEAPSettingsTable"), 		    //KCDTIdLEAPRecord
+			_S("PolicySelectorTable"),			//KCDTIdPolicySelectorRecord
+			_S("PolicySelector2QosParametersTable"),	//KCDTIdPolicySelector2ParamsRecord
+			_S("GenericQosTable")				//KCDTIdGenericQosRecord
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+            };
+
+
+        const TMDBElementId tmdbElementsForPairing[] =
+            {
+            KCDTIdNetworkRecord,
+            KCDTIdIAPRecord,
+            KCDTIdModemBearerRecord,
+            KCDTIdLANBearerRecord,
+            KCDTIdLANServiceRecord,
+            KCDTIdDialInISPRecord,
+            KCDTIdDialOutISPRecord,
+            KCDTIdAgentLookupRecord,
+            KCDTIdChargecardRecord,
+            KCDTIdConnectionPrefsRecord,
+            KCDTIdGlobalSettingsRecord,
+            KCDTIdIncomingGprsRecord,
+            KCDTIdOutgoingGprsRecord,
+            //NOKIA magic...>,
+            KCDTIdProxiesRecord,
+            KCDTIdLocationRecord,
+            KCDTIdSSProtoRecord,
+            //not used anymore>,
+            //not used anymore>,
+            //not used anymore>,
+            //not used anymore>,
+            KCDTIdWAPAccessPointRecord,
+            KCDTIdWAPIPBearerRecord,
+            KCDTIdWAPSMSBearerRecord,
+            KCDTIdVirtualBearerRecord,
+            KCDTIdVPNServiceRecord,
+            KCDTIdWLANServiceExtRecord,
+            KCDTIdPANServiceExtRecord,
+            KCDTIdEAPSecRecord,
+            KCDTIdTunEAPRecord,
+            KCDTIdEAPTLSRecord,
+#ifndef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+            KCDTIdLEAPRecord
+#else
+            KCDTIdLEAPRecord,
+			KCDTIdPolicySelectorRecord,
+			KCDTIdPolicySelector2ParamsRecord,
+			KCDTIdGenericQosRecord
+#endif //SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+            };
+
+#ifndef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+        const TInt KPairNumber = 27; //number of pairs in the above arrays
+#else
+		const TInt KPairNumber = 30; //number of pairs in the above arrays
+#endif
+
+        TUint32 DoHash(const TPtrC& aText)
+            {
+            return DefaultHash::Des16(aText);
+            }
+
+        TBool AreTheKeysIdentical(const TPtrC& aKey1, const TPtrC& aKey2)
+            {
+            return (aKey1 == aKey2);
+            }
+    } //end of anonymous namespace
+
+//
+// CXMLContentHandler
+//
+const TInt CXMLContentHandler::KExpectedLeaveCode = 1234;
+
+CXMLContentHandler* CXMLContentHandler::NewL( CXMLDatabase* aXmlDb,
+		                                      const TBool aForceFlag,
+		                                      const TBool aAppendFlag )
+    {
+    CXMLContentHandler* self = new(ELeave) CXMLContentHandler(aXmlDb,aForceFlag,aAppendFlag);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+    }
+
+CXMLContentHandler::CXMLContentHandler(CXMLDatabase* aXmlDb,
+		                               const TBool aForceFlag,
+		                               const TBool aAppendFlag) :
+    iLeaveOnStartElement(EFalse),
+    iNumElements(0),
+    iNumSkippedEntities(0),
+    iNumPrefixMappings(0),
+    iNumPrefixUnmappings(0),
+    iError(KErrNone),
+    iXmlDb(aXmlDb),
+    iForceXMLProcessing(aForceFlag),
+    isInAppendMode(aAppendFlag),
+    iXMLContentState(ENone)
+	{
+	iCurrentTableName.Copy(_L(""));
+	iCurrentRecordName.Copy(_L(""));
+	iCurrentParameterValue.Copy(_L(""));
+	iCurrentParameter.Copy(_L(""));
+	}
+
+void CXMLContentHandler::ConstructL()
+    {
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+    iCmdbSession = CMDBSession::NewL(KCDVersion1_2);
+#else
+    iCmdbSession = CMDBSession::NewL(KCDVersion1_1);
+#endif
+
+    THashFunction32<TPtrC> hashFunc(&DoHash);
+    TIdentityRelation<TPtrC> idRel(&AreTheKeysIdentical);
+
+    iTableNameIDpairs = new(ELeave) RHashMap<TPtrC, TMDBElementId>(hashFunc, idRel);
+    FillUpHashMapL(*iTableNameIDpairs);
+    }
+
+CXMLContentHandler::~CXMLContentHandler()
+	{
+	delete iCmdbSession;
+	iCmdbSession = NULL;
+
+	iTableNameIDpairs->Close();
+    delete iTableNameIDpairs;
+    iTableNameIDpairs = NULL;
+	}
+
+// When the beginning of the document is encountered then all counters
+// are initialised
+void CXMLContentHandler::OnStartDocumentL(const RDocumentParameters&, TInt)
+	{
+	iNumElements         = 0;
+	iNumSkippedEntities  = 0;
+	iNumPrefixMappings   = 0;
+	iNumPrefixUnmappings = 0;
+	}
+
+void CXMLContentHandler::OnEndDocumentL(TInt)
+	{
+	}
+
+// At the beginning of an XML element we need to find out what does the element
+// represent
+void CXMLContentHandler::OnStartElementL(const RTagInfo& aInfo, const RAttributeArray& attribs, TInt)
+	{
+	if (iLeaveOnStartElement)
+		{
+		if (iNumElements++ == 0)
+			{
+			User::Leave(KExpectedLeaveCode);
+			}
+		}
+
+	iNumElements++;
+
+	// Get the name of the tag
+	//
+	const TDesC8& name = aInfo.LocalName().DesC();
+	TBuf<MAX_BUFFER_LEN> tag;
+	tag.Copy(name);
+
+	TBuf<MAX_BUFFER_LEN> thisTag;
+
+    switch (iXMLContentState)
+        {
+        case ENone:
+            {
+
+        	// We avoid the "Config" and "InformationTable" tags as well as
+        	// the parameters of the "InformationTable" which are not supported
+        	// in this version
+        	if (tag.Compare(_L("Config")) == 0)
+        		{
+        		gMsg->Msg(_L("Avoiding Config element"));
+        		return;
+        		}
+
+        	if (tag.Compare(_L("InformationTable")) == 0)
+        		{
+        		iXMLContentState = EInDeprecatedTable;
+        		iCurrentTableName.Copy(tag);
+        		gMsg->Msg(_L("Start of the InformationTable element"));
+        		return;
+        		}
+
+        	// See if this tagname is a table
+
+        	TInt                 i = 0;
+        	TBuf<MAX_BUFFER_LEN> tableName;
+        	thisTag = xmlTableArray[0];
+
+
+        	while (thisTag.Compare(TPtrC(NO_MORE_RECORDS)) != 0)
+        		{
+        		tableName = thisTag;
+        		tableName.Append(_L("Table"));
+
+        		// Check if this is a table
+        		//
+        		if (tableName.Compare(tag) == 0)
+        			{
+                	// If the parsed element is a table then save the name of this
+                	// table for later use when creating table entries
+                	//
+                    iXMLContentState = EInTable;
+            		iCurrentTableName.Copy(tableName);
+            		gMsg->Msg(_L("Located table : [%S]"), &tableName);
+            		return;
+        			}
+        		i++;
+        		thisTag = xmlTableArray[i];
+        		}
+
+            // If we've got here then there must have been some weirdness in the input file, still
+            // perhaps if we carry on, we'll sort ourselves out...
+
+    		gMsg->Msg(_L("ERR: Unknown or deprecated table : [%S]"), &tag);
+    		iXMLContentState = EInDeprecatedTable;
+    		iCurrentTableName.Copy(tag);
+            }
+        	break;
+
+        case EInDeprecatedTable:
+        	return;
+        case EInTable:
+            {
+        	// Examine if this tagname is a record
+
+        	TInt i       = 0;
+        	     thisTag = xmlTableArray[0];
+        	while (thisTag.Compare(TPtrC(NO_MORE_RECORDS)) != 0)
+        		{
+        		// Check whether this is a table entry
+        		//
+        		if (thisTag.Compare(tag) == 0)
+        			{
+                	// If the parsed element is a table entry then create a new CXMLTableEntry
+                	// object and add it to the XML database
+
+        			iXMLContentState = EInRecord;
+        			iCurrentRecordName.Copy(thisTag);
+
+            		CXMLTableEntry* tableEntry = CXMLTableEntry::NewL(iCurrentTableName);
+            		TBuf<MAX_BUFFER_LEN> operation;
+            		if(attribs.Count() == 0)
+            		    {
+            			operation.Copy(_L("add"));
+            			}
+            		else
+            		    {
+            			operation.Copy(attribs[0].Value().DesC());
+            			}
+
+            		tableEntry->SetOperation(operation);
+
+            		gMsg->Msg(_L("Create new table entry for table : [%S] with operation (%S)"),
+                            			&iCurrentTableName, &operation);
+            		iXmlDb->AddTableEntry(tableEntry);
+            		return;
+        			}
+
+        		i++;
+        		thisTag = xmlTableArray[i];
+        		}
+
+
+            // If we've got here then there must have been some weirdness in the input file, still
+            // perhaps if we carry on, we'll sort ourselves out...
+
+    		gMsg->Msg(_L("ERR: Unknown record : [%S]"), &tag);
+            if (!iForceXMLProcessing)
+                {
+    			User::Leave(KErrCorrupt);
+                }
+            }
+        	break;
+
+        case EInRecord:
+            {
+        	// If the parsed element is not a table or a table entry then it
+        	// represents the beginning of the specification of a table entry
+        	// parameter. In this case we need to set the name of this element
+        	// as a new parameter for the table entry we last created. Note that
+        	// the value of the parameter will be picked by a call to the
+        	// OnContentL function
+
+        	iXMLContentState = EInParam;
+
+        	CXMLTableEntry* lastEntry = iXmlDb->GetLastTableEntry();
+        	iCurrentParameter.Copy(tag);
+        	lastEntry->AddParameterL(tag, _L(""));
+        	gMsg->Msg(_L("Create new parameter : [%S]"), &tag);
+
+        	/**
+        	Set the linking type to default - ENot_A_Link. Later on this will be
+        	changed.
+        	*/
+        	lastEntry->SetLinkType(CXMLTableEntry::ENot_A_Link);
+        	}
+        	break;
+
+        default:
+            break;
+        }
+	} // OnStartElementL()
+
+
+void CXMLContentHandler::OnEndElementL(const RTagInfo& aInfo, TInt)
+	{
+	// Get the name of the tag
+    const TDesC8& name = aInfo.LocalName().DesC();
+    TBuf<MAX_BUFFER_LEN> tag;
+	tag.Copy(name);
+
+	// Reset the name of the current table if we reached the end of the table
+
+    switch (iXMLContentState)
+        {
+        case EInDeprecatedTable:
+    		{
+            if (tag.Compare(iCurrentTableName) == 0)
+        		{
+        		iCurrentTableName.Copy(_L(""));
+        		gMsg->Msg(_L("Reached end of deprecated table [%S]"), &tag);
+	    		iXMLContentState = ENone;
+				}
+    		else
+        	    {
+                gMsg->Msg(_L("ERR: Use of [%S] inside deprecated [%S]"), &tag, &iCurrentTableName);
+#ifdef SYMBIAN_NETWORKING_3GPPDEFAULTQOS
+				gDeprecatedFields = ETrue;
+#endif
+        	    }
+
+    		}
+        	break;
+        case EInTable:
+            {
+    		iXMLContentState = ENone;
+            if (tag.Compare(iCurrentTableName) == 0)
+        		{
+        		iCurrentTableName.Copy(_L(""));
+        		gMsg->Msg(_L("Reached end of table [%S]"), &tag);
+        		}
+        	else
+        	    {
+                gMsg->Msg(_L("Error parsing table [%S]"), &tag);
+                if (!iForceXMLProcessing)
+                    {
+        			User::Leave(KErrCorrupt);
+                    }
+        	    }
+        	}
+        	break;
+
+        case EInRecord:
+            {
+            iXMLContentState = EInTable;
+            if (tag.Compare(iCurrentRecordName) == 0)
+        		{
+        		iCurrentRecordName.Copy(_L(""));
+        		gMsg->Msg(_L("Reached end of record [%S]"), &tag);
+        		}
+        	else
+        	    {
+        		gMsg->Msg(_L("Error parsing record [%S]"), &tag);
+                if (!iForceXMLProcessing)
+                    {
+        			User::Leave(KErrCorrupt);
+                    }
+                }
+            }
+        	break;
+
+        case EInParam:
+            {
+            iXMLContentState = EInRecord;
+        	if (tag.Compare(iCurrentParameter) == 0)
+        		{
+        		// Pick the last table entry added to the database
+        		CXMLTableEntry* lastEntry = iXmlDb->GetLastTableEntry();
+        		TInt lastParamIndex = lastEntry->GetNumberParameters()-1;
+
+        		// Examine to see if the content is simply the return
+        		// character which indicates that there is no assigned
+        		// value for this parameter
+        		TInt loc = iCurrentParameterValue.Locate('\n');
+
+        		if (loc == 0)
+        			{
+        			lastEntry->RemoveParameter(lastParamIndex);
+                    return;
+        			}
+
+        		// Set the value of the last parameter for this table entry
+        		lastEntry->SetParameterValue(lastParamIndex, iCurrentParameterValue);
+
+        		gMsg->Msg(_L("Set parameter value to : [%S]"), &iCurrentParameterValue);
+        		iCurrentParameterValue.Copy(_L(""));
+        		}
+        	else
+        	    {
+        		gMsg->Msg(_L("Error parsing parameter [%S]"), &tag);
+                if (!iForceXMLProcessing)
+                    {
+        			User::Leave(KErrCorrupt);
+                    }
+        	    }
+        	}
+            break;
+
+        default:
+            break;
+        }
+	} // OnEndElementL()
+
+
+void CXMLContentHandler::OnContentL(const TDesC8& aContent, TInt)
+	{
+    // If we are currently processing table entry parameters then the
+	// content represents a fragment of the value of the recently
+	// created parameter
+
+	if (iXMLContentState == EInParam)
+		{
+		TBuf<MAX_BUFFER_LEN> temp;
+		temp.Copy(aContent);
+		iCurrentParameterValue.Append(temp);
+		}
+	}
+
+void CXMLContentHandler::OnProcessingInstructionL(const TDesC8&, const TDesC8&, TInt)
+	{
+	}
+
+void CXMLContentHandler::OnError(TInt aError)
+	{
+	gMsg->Msg(_L("ERR: Error parsing xml, err=%d"), aError);
+	iError = aError;
+	}
+
+TAny* CXMLContentHandler::GetExtendedInterface(const TInt32)
+	{
+	return NULL;
+	}
+
+void CXMLContentHandler::OnStartPrefixMappingL(const RString&, const RString&, TInt)
+	{
+	iNumPrefixMappings++;
+	}
+
+void CXMLContentHandler::OnEndPrefixMappingL(const RString&, TInt)
+	{
+	iNumPrefixUnmappings++;
+	}
+
+void CXMLContentHandler::OnIgnorableWhiteSpaceL(const TDesC8&, TInt)
+	{
+	}
+
+void CXMLContentHandler::OnSkippedEntityL(const RString&, TInt)
+	{
+	iNumSkippedEntities++;
+	}
+
+void CXMLContentHandler::OnExtensionL(const RString&, TInt, TInt)
+	{
+	}
+
+// Set the IDs for all table entries
+void CXMLContentHandler::SetTableIDs()
+	{
+	TInt iEntry;
+	TInt entryId = 1;
+
+    for (iEntry = 1; iEntry < iXmlDb->GetNumberTableEntries(); iEntry++)
+		{
+		CXMLTableEntry* entry = iXmlDb->GetTableEntry(iEntry);
+        const TBuf<MAX_BUFFER_LEN>& tableName    = entry->GetTableName();
+        const TBuf<MAX_BUFFER_LEN>& tableNamePre = iXmlDb->GetTableEntry(iEntry-1)->GetTableName();
+
+		if(tableName.Compare(tableNamePre) == 0)
+		    {
+			entryId++;
+		    }
+		else
+		    {
+			entryId = 1;
+		    }
+
+		entry->SetEntryId(entryId);
+		}
+	}
+
+// Some table entries in CommDB do not have a "Name" parameter although
+// in the XML format all table entries must have such a parameter in order
+// to allow table entry referencing. The following loop removes the
+// "Name" parameter from these table entries
+void CXMLContentHandler::RemoveNameParams()
+	{
+	for (TInt iEntry = 0; iEntry < iXmlDb->GetNumberTableEntries(); iEntry++)
+		{
+		CXMLTableEntry* entry = iXmlDb->GetTableEntry(iEntry);
+        const TBuf<MAX_BUFFER_LEN>& tableName = entry->GetTableName();
+
+		for(TInt i = 0; i < numNoNameTables; i++)
+			{
+			if(tableName.Compare(TPtrC(noNameTables[i])) == 0)
+				{
+				TInt numParams = entry->GetNumberParameters();
+
+				// Loop through all the parameters of the current table entry
+				for(TInt iParam = 0; iParam < numParams; iParam++)
+					{
+					const TBuf<MAX_BUFFER_LEN>& paramName = entry->GetParameterName(iParam);
+
+					// Check if this parameter needs modification.
+					if(paramName.Compare(_L("Name")) == 0)
+						{
+						entry->RemoveParameter(iParam);
+						break;
+						}
+					}
+				}
+			}
+		}
+	}
+
+ /**
+ * This function sets the <TableName>.<RecordID> linking in the
+ * case of a linked record in the XML file. So from this point the
+ * processing of the linked record can continue like in the case of
+ * regular cfg files.
+ */
+void CXMLContentHandler::SetCfgLinkingFromXMLFile(const TDesC&          aRefTable,
+                                                  const TInt            aParamIndex,
+                                                        CXMLTableEntry* aEntry)
+    {
+    TBool finished = EFalse;
+
+    for (TInt i = 0; (!finished) && (i < LinkedRecordTableNum); ++i)
+        {
+        TPtrC linkedRecordTableName(LinkedRecordTableNames[i]);
+
+        if ( linkedRecordTableName == aEntry->GetTableName() )
+            {
+            /**
+              OK, got the table name index. Based on this let's check
+              the name of the linked record...
+              1 loop for the paramName array in the entry, the other is for the LinkRecordsArray[i]
+            */
+
+            for (TInt j = 0; (!finished) && ((TPtrC(LinkRecordsArray[i][j])) != TPtrC(NO_MORE_RECORDS)); ++j)
+                {
+                TPtrC linkedRecordFromArray(LinkRecordsArray[i][j]);
+
+                if ( linkedRecordFromArray == aEntry->GetParameterName(aParamIndex) )
+                /**
+                 * YESSSSS, we have found a linked record. Currently it contains only the
+                 * recordID of the referenced record. This should be changed to
+                 * Link.tableName.recordID which is in our case the
+                 * Link.<aRefTable>.<current recordID>
+                 */
+                    {
+                    TBuf<MAX_BUFFER_LEN> buf;
+                    /**
+                     * It would be simpler if the Append(TDesc16) would return with a
+                     * 'this' reference...
+                     */
+                    buf.Append(aRefTable);
+                    buf.Append(TPtrC(_S(".")));
+                    buf.Append(aEntry->GetParameterValue(aParamIndex));
+                    aEntry->SetParameterValue(aParamIndex, buf);
+
+                    finished = ETrue;
+                    }
+                }
+            }
+        }
+    }
+
+/**
+ * This funciton is called if the record referencing from the XML db is not
+ * successful. In this case we try to relove the references from the existing
+ * database.
+ * DEF103749
+ */
+TBool CXMLContentHandler::ResolveRefsFromDbL(CXMLTableEntry*             entry,
+                                			const TInt                  paramIndex,
+                                			const TPtrC&                refEntryName,
+                                			const TPtrC&                refEntryTable,
+                                			const TPtrC&                orgEntryTable)
+    {
+    TBool retCode = EFalse;
+
+    TMDBElementId elemendID;
+
+	elemendID = iTableNameIDpairs->FindL(refEntryTable);
+
+    //read all of the records form a given table (entry->GetTableName)
+	CMDBRecordSetBase* recordFromDb = new(ELeave) CMDBRecordSetBase(elemendID);
+	CleanupStack::PushL(recordFromDb);
+
+	recordFromDb->LoadL(*iCmdbSession);
+
+    for (TInt i = 0; (!retCode) && (i<recordFromDb->iRecords.Count()); ++i)
+        {
+        if ( CXMLTableEntry::EResolve_XML_Ref == entry->GetLinkType(paramIndex) )
+        //The linking is tableName.RecordName
+            {
+            CMDBField<TDesC> *afn = NULL;
+            TInt temp = 0;
+            CMDBElement* element = recordFromDb->iRecords[i]->GetFieldByNameL(_L("Name"), temp );
+
+            afn = static_cast<CMDBField<TDesC> *>(element);
+
+            TPtrC name(*afn);
+            if (name == refEntryName)
+            //OK, found the refenced record in the db.
+                {
+                TInt recId = recordFromDb->iRecords[i]->RecordId();
+
+            	TBuf<MAX_BUFFER_LEN> buf;
+    			buf.Format(_L("%D"), recId);
+    			entry->SetParameterValue(paramIndex,buf);
+
+    			SetCfgLinkingFromXMLFile(orgEntryTable, paramIndex, entry);
+
+    			retCode = ETrue;
+                }
+            }
+        else
+        //The linking is tableName.recordID
+            {
+            if ( recordFromDb->iRecords[i]->RecordId() == entry->GetRecordID() )
+            //OK, found the referenced record in the DB.
+                {
+                if ( entry->GetParameterName(paramIndex) == TPtrC(_S("IAPService")) ||
+	                     entry->GetParameterName(paramIndex) == TPtrC(_S("IAPBearer")) )
+			            {
+			            TBuf<MAX_BUFFER_LEN> buf;
+    			        buf.Format(_L("%D"), recordFromDb->iRecords[i]->RecordId());
+
+    				    entry->SetParameterValue(paramIndex,buf);
+			            }
+
+    				retCode = ETrue;
+                }
+            }
+        }
+
+        CleanupStack::PopAndDestroy(recordFromDb);
+
+    return retCode;
+    }
+
+
+/**
+This function fills up the HashMap, which is used to resolve refences
+from the existing databse.
+*/
+void CXMLContentHandler::FillUpHashMapL(RHashMap<TPtrC, TMDBElementId>& aHashMap)
+    {
+    for (TInt i = 0; i < KPairNumber; ++i)
+        {
+        //Temporary can be used as the parameters (1st param) because RHashMap copies the elements
+        aHashMap.InsertL(TPtrC(tableNamesForPairing[i]), tmdbElementsForPairing[i]);
+        }
+    }
+
+// Resolve the table entry references specified in the XML configuration file
+TBool CXMLContentHandler::ResolveTableEntryReferences(CXMLTableEntry* entry,
+                                                      const TInt paramIndex,
+                                                      const TBuf<MAX_BUFFER_LEN>& refEntryName,
+                                                      const TBuf<MAX_BUFFER_LEN>& refEntryTable,
+                                                      const TBuf<MAX_BUFFER_LEN>& orgEntryTable)
+	{
+    // If the name of the referenced table entry is "-1"
+    // i.e. it does not exist, then the ID is set to "0"
+    if(refEntryName.Compare(_L("-1")) == 0)
+		{
+        if(entry->GetOperation().Compare(_L("template")) == 0)
+			{
+            entry->SetParameterValue(paramIndex,_L("0"));
+            return ETrue;
+			}
+        else
+			{
+			gMsg->Msg(_L("Cannot resolve table entry reference : [%S.%S]"), &refEntryTable, &refEntryName);
+			gMsg->Msg(_L("CED terminates without generating a CommDB database"));
+			return EFalse;
+			}
+		}
+
+	if ( CXMLTableEntry::ESkip_XML__Ref == entry->GetLinkType(paramIndex) )
+	/**
+	We have a link with tablename.-1 referencing. Skip it...
+	*/
+	    {
+	    return ETrue;
+	    }
+
+	// Find the ID of the table entry referenced
+    for (TInt k = 0; k < iXmlDb->GetNumberTableEntries(); k++)
+		{
+        CXMLTableEntry* lookEntry = iXmlDb->GetTableEntry(k);
+
+		// Look for table entries which belong to the table
+        // we are looking for
+        if(lookEntry->GetTableName().Compare(refEntryTable) == 0)
+			{
+			if (CXMLTableEntry::EResolve_XML_Ref == entry->GetLinkType(paramIndex))
+			/**
+			The linking is by record name...
+			*/
+			    {
+    			for(TInt m = 0; m < lookEntry->GetNumberParameters(); m++)
+    				{
+    				const TBuf<MAX_BUFFER_LEN>& param = lookEntry->GetParameterName(m);
+    				if(param.Compare(_L("Name")) == 0)
+    					{
+    					const TBuf<MAX_BUFFER_LEN>& name = lookEntry->GetParameterValue(m);
+    					if(name.Compare(refEntryName) == 0)
+    						{
+    				        TBuf<MAX_BUFFER_LEN> buf;
+    					    buf.Format(_L("%D"), lookEntry->GetRecordID());
+
+    				        entry->SetParameterValue(paramIndex,buf);
+
+        					SetCfgLinkingFromXMLFile(orgEntryTable, paramIndex, entry);
+
+    						return ETrue;
+    						}
+
+    						break;
+    					}
+    				}
+			    }
+			else
+			/**
+			The linking is by recordID...
+			*/
+			    {
+				TLex16 conv(refEntryName);
+	            TInt recId  = 0;
+	            TInt err = conv.Val(recId);
+
+			    if (err == KErrNone && recId == lookEntry->GetRecordID())
+			    //We have found the referenced record in the XMLDB
+			        {
+			        if ( entry->GetParameterName(paramIndex) == TPtrC(_S("IAPService")) ||
+	                     entry->GetParameterName(paramIndex) == TPtrC(_S("IAPBearer")) )
+			            {
+			            TBuf<MAX_BUFFER_LEN> buf;
+    			        buf.Format(_L("%D"), lookEntry->GetRecordID());
+
+    				    entry->SetParameterValue(paramIndex,buf);
+			            }
+
+    				return ETrue;
+			        }
+			    }
+			}
+		}
+
+	// If we reach this point then the ID cannot be resolved. In this case
+	// we have the following options:
+	//
+	// 1. If the table entry currently processing is a template then this
+	// is expected.
+	//
+	// 2. If the table entry currently processing is not a template then
+	// the program terminates if CED is running with the "-F" flag. Else
+	// we set the ID equal to the refered table entry name converted to an
+	// integer
+
+	if (iForceXMLProcessing)
+	    {
+	    if (entry->GetOperation().Compare(_L("template")) == 0)
+    		{
+    		TLex16 conv(refEntryName);
+    		TInt id  = 0;
+    		TInt err = conv.Val(id);
+
+    		if(err == KErrNone)
+    			{
+    			TBuf<MAX_BUFFER_LEN> buf;
+    			buf.Format(_L("%D"),++id);
+    			entry->SetParameterValue(paramIndex,buf);
+    			}
+
+    		return ETrue;
+    		}
+        else
+            {
+            TBool ret = EFalse;
+    	    TRAPD(leavingError, ret = ResolveRefsFromDbL(entry, paramIndex, refEntryName, refEntryTable, orgEntryTable));
+
+            if (!leavingError)
+                {
+                if (!ret)
+                    {
+                    gMsg->Msg(_L("Cannot resolve table entry reference from the DB: [%S.%S]"), &refEntryTable, &refEntryName);
+			        gMsg->Msg(_L("CED terminates without generating a CommDB database"));
+                    }
+                return ret;
+                }
+            else
+                {
+                gMsg->Msg(_L("Cannot resolve table entry reference from the DB: [%S.%S]"), &refEntryTable, &refEntryName);
+			    gMsg->Msg(_L("CED terminates without generating a CommDB database"));
+
+			    return EFalse;
+                }
+
+            }
+	    }
+	else
+		{
+		gMsg->Msg(_L("Cannot resolve table entry reference : [%S.%S]"), &refEntryTable, &refEntryName);
+		gMsg->Msg(_L("CED terminates without generating a CommDB database"));
+		return EFalse;
+		}
+	}
+
+/**
+ * Map the recordIDs from the database into the data structure in which the
+ * the xml elements are stored. It is needed for the proper linking.
+ * DEF103749
+ */
+void CXMLContentHandler::SetRecordIDsL()
+    {
+    //RAII
+    TMDBElementId elemendID      = 0;
+
+	TInt entryNum                = 0,
+	     tempEntryNum            = 0,
+	     baseRecordID            = 0;
+
+	TBool entryEnd               = EFalse;
+
+	CXMLTableEntry* entry        = NULL,
+	              * tempEntry    = NULL;
+
+	CMDBRecordBase* recordFromDb = NULL;
+
+	while (entryNum < iXmlDb->GetNumberTableEntries())
+		{
+		entry = iXmlDb->GetTableEntry(entryNum);
+
+	    if ( TPtrC(_S("template")) == entry->GetOperation() )
+	     /**
+	     * Handling templates is a bit trickier than simple addings...
+	     *
+	     * Note: it's not handled here when 1 table contains more tham 1 template records in the
+	     * config file...
+	     * Should CED be prepared for this????????????????????????
+	     */
+	        {
+	        if (isInAppendMode)
+	            {
+    	        elemendID = iTableNameIDpairs->FindL(entry->GetTableName());
+
+            	// Enable ECDHidden on session to be able to read the template records
+            	iCmdbSession->SetAttributeMask(ECDHidden);
+
+
+            	recordFromDb = new(ELeave) CMDBRecordBase(elemendID);
+            	CleanupStack::PushL(recordFromDb);
+
+                recordFromDb->SetRecordId(KCDDefaultRecord);
+
+            	/**
+            	 * This leave has to be trapped becasuse CED should be prepared for the
+            	 * cases where a template record is already existing in the given
+            	 * table.
+            	 */
+            	TRAPD(leavingError, recordFromDb->LoadL(*iCmdbSession));
+
+            	if (!leavingError)
+            	/**
+            	 * The LoadL didn't leave, which means that we have already a template
+            	 * record for the given table in the database. The record read from the xml
+            	 * file cannot be appended.
+            	 */
+            	    {
+            	    gMsg->Msg(_L("Warning - Duplicate TEMPLATE records for the table: [%S]"),&entry->GetTableName());
+            	    gMsg->Msg(_L("Skipping it..."));
+
+            	    entry->SetDeleteFlag(ETrue);
+            	    }
+            	else
+            	/**
+            	 * The given table doesn't have yet a template record so the one which was read from
+            	 * the xml file can be appended.
+            	 */
+            	    {
+            	    entry->SetRecordID(0);
+            	    }
+
+            	CleanupStack::PopAndDestroy(recordFromDb);
+        	    recordFromDb = NULL;
+	            }
+        	else
+            /**
+             * Simply give the record number 0 for the template record as we are not in append mode.
+             */
+        	    {
+        	    entry->SetRecordID(0);
+        	    }
+
+
+        	// Disable ECDNoWriteButDelete on session
+        	iCmdbSession->ClearAttributeMask(ECDHidden);
+
+        	++entryNum;
+	        }
+	    else
+	    /**
+	     * Simple addings...
+	     */
+	        {
+    	    if (isInAppendMode)
+    	        {
+        	    TRAPD(leavingError, elemendID = iTableNameIDpairs->FindL(entry->GetTableName()));
+
+            	if (!leavingError)
+	            	{
+	            	CMDBRecordSetBase* recordSetFromDb = new(ELeave) CMDBRecordSetBase(elemendID);
+    	        	CleanupStack::PushL(recordSetFromDb);
+
+        	    	recordSetFromDb->LoadL(*iCmdbSession);
+
+            		TInt recIdMax = 0;
+
+            		for (TInt i = 0; i<recordSetFromDb->iRecords.Count(); ++i)
+                    	{
+                    	recordFromDb = recordSetFromDb->iRecords[i];
+
+                    	if (recordFromDb->RecordId() > recIdMax)
+                        	recIdMax = recordFromDb->RecordId();
+                    	}
+
+        	    	baseRecordID = recIdMax+1;
+
+        	    	CleanupStack::PopAndDestroy(recordSetFromDb);
+	            	}
+	            else
+	            	{
+	           	    gMsg->Msg(_L("Warning - cannot append records to the table: [%S]"),&entry->GetTableName());
+            	    gMsg->Msg(_L("Skipping it..."));
+
+            	    entry->SetDeleteFlag(ETrue);
+	            	}
+    	        }
+    	    else
+    	        {
+    	        baseRecordID = 1;
+    	        }
+
+    	    entryEnd = EFalse;
+
+    		for (tempEntryNum = entryNum;
+    		     (!entryEnd) && (tempEntryNum < iXmlDb->GetNumberTableEntries());
+    		     ++tempEntryNum)
+    		    {
+    		    tempEntry = iXmlDb->GetTableEntry(tempEntryNum);
+
+    		    if (entry->GetTableName() != tempEntry->GetTableName())
+    		        {
+    		        entryEnd = ETrue;
+    		        break;
+    		        }
+    		    else
+    		        {
+    		        tempEntry->SetRecordID(baseRecordID++);
+    		        }
+
+    		    entryNum = entryNum+(tempEntryNum-entryNum)+1;
+
+    		    }
+	        }
+        }
+    }
+
+
+// CommDB requires the conversion of the references to table entries using the qualified
+// name scheme of the XML configuration file to one which employs a table entry ID and
+// an additional parameter which indicates the name of the table the entry belongs to
+TBool CXMLContentHandler::ModifyTableEntryReferencesL()
+	{
+	// Set the IDs for all table entries
+    SetTableIDs();
+
+    TRAPD(leavingError, SetRecordIDsL());
+
+    if (KErrNone != leavingError)
+        return EFalse;
+
+    //if some entrys have the deleted flag true they are deleted here...
+    iXmlDb->CheckDeletedElems();
+
+	// Modify the table references
+
+    for (TInt iEntry = 0; iEntry < iXmlDb->GetNumberTableEntries(); iEntry++)
+		{
+		CXMLTableEntry* entry = iXmlDb->GetTableEntry(iEntry);
+
+		// Loop through all the table parameters to modify
+		for(TInt iMod = 0; iMod < numMods; iMod++)
+			{
+			const TBuf<MAX_BUFFER_LEN>& modName = modParam[iMod];
+
+			// Look for table entries which belong to the table
+			// we need to modify
+
+			if(entry->GetTableName().Compare(TPtrC(modTable[iMod])) == 0)
+				{
+				// Loop through all the parameters of the current table entry
+				for(TInt iParam = 0; iParam < entry->GetNumberParameters(); iParam++)
+					{
+					const TBuf<MAX_BUFFER_LEN>& paramName = entry->GetParameterName(iParam);
+
+					// Check if this parameter needs modification.
+					if(paramName.Compare(modName) == 0)
+						{
+						// Extract the value of the name of the table the table entry
+						// reference belongs to as well as the name of the table entry
+						const TBuf<MAX_BUFFER_LEN>& paramValue = entry->GetParameterValue(iParam);
+
+						gMsg->Msg(_L("Modifying Parameter : [%S] = [%S]"),&paramName,&paramValue);
+
+						TBuf<MAX_BUFFER_LEN> refEntryTable;
+						TInt k, m;
+
+						for(k = 0; k < paramValue.Length(); k++)
+							{
+							TChar c = paramValue[k];
+							if(c == TChar('.')) break;
+							refEntryTable.Append(c);
+							}
+
+                        TBuf<MAX_BUFFER_LEN> orgEntryTable;
+                        orgEntryTable.Copy(refEntryTable);
+                        refEntryTable.Append(_L("Table"));
+
+						gMsg->Msg(_L("  Referenced Table Name = [%S]"),&refEntryTable);
+
+						if (!IsTableKnown(orgEntryTable))
+							{
+							//The referenced table is not supported anymore. Skip it...
+							gMsg->Msg(_L("ERR: Referenced Table Name = [%S] is not known by CED. Skipping it..."),&refEntryTable);
+							}
+						else
+							{
+	                        TBuf<MAX_BUFFER_LEN> refEntryName;
+							for(m = k+1; m < paramValue.Length(); m++)
+								refEntryName.Append(paramValue[m]);
+
+							gMsg->Msg(_L("  Referenced Table Entry Name = [%S]"),&refEntryName);
+
+							// Rename the modified parameter
+							entry->RenameParameter(iParam,newModParam[iMod]);
+
+							/**
+							Setting the linking type - if any
+							*/
+							TLex16 conv(refEntryName);
+	    		            TInt recId  = 0;
+	    		            TInt err = conv.Val(recId);
+
+	                		if(err == KErrNone)
+	                		/**
+	                		  OK, the conversion is successful. Let's see whether is it a non relevant link
+	                		  (tableName.-1) or a relevant one...
+	                		*/
+	                			{
+	                			if (-1 == recId)
+	                			/**
+	                			The link can be skipped...
+	                			*/
+	                			    {
+	                			    entry->ModifyLinkType(iParam, CXMLTableEntry::ESkip_XML__Ref);
+	                			    }
+	                            else
+	                            /**
+	                            The reference is by record id...
+	                            */
+	                                {
+	                                entry->ModifyLinkType(iParam, CXMLTableEntry::ERecord_ID_Reference);
+	                                }
+	                			}
+	                		else
+	                		/**
+	                		The conversion wasn't successful, so the given reference is
+	                		not record ID.
+	                		*/
+	                		    {
+	                		    entry->ModifyLinkType(iParam, CXMLTableEntry::EResolve_XML_Ref);
+	                		    }
+
+							// If the name of the table must be specified then add
+							// an additional parameter for that purpose
+							if(TPtrC(typeParam[iMod]).Compare(_L("")) != 0)
+								{
+								if(orgEntryTable.Compare(_L("Proxy")) == 0)
+									orgEntryTable.Copy(_L("Proxies"));
+								else if(orgEntryTable.Compare(_L("BTDevice")) == 0)
+									orgEntryTable.Append(_L("Table"));
+								else if(orgEntryTable.Compare(_L("BTDefault")) == 0)
+									orgEntryTable.Append(_L("Table"));
+								else if(orgEntryTable.Compare(_L("BTSecurity")) == 0)
+									orgEntryTable.Append(_L("Table"));
+								else if(orgEntryTable.Compare(_L("BTPersist")) == 0)
+									orgEntryTable.Append(_L("Table"));
+								else if(orgEntryTable.Compare(_L("SecureSocket")) == 0)
+									orgEntryTable.Append(_L("Table"));
+								else if(orgEntryTable.Compare(_L("UmtsR99QoSAndOn")) == 0)
+									orgEntryTable.Append(_L("Table"));
+
+								entry->AddParameterL(typeParam[iMod],orgEntryTable);
+								}
+
+	                        // Resolve the table entry references
+	                        TBool bResolved = ResolveTableEntryReferences(entry,iParam,refEntryName,refEntryTable, orgEntryTable);
+
+	                        if(!bResolved)
+	                            {
+	                            return EFalse;
+	                            }
+							}
+						}
+					}
+				}
+			}
+		}
+
+	// Some table entries in CommDB do not have a "Name" parameter although
+	// in the XML format all table entries must have such a parameter in order
+	// to allow table entry referencing. The following loop removes the
+	// "Name" parameter from these table entries
+    RemoveNameParams();
+
+    return ETrue;
+	}
+
+// Dump the contents of the table entries on the log file
+void CXMLContentHandler::LogTableEntries()
+	{
+	gMsg->Msg(_L("Log Dump of CommDB Table Contents"));
+
+	for (TInt iEntry = 0; iEntry < iXmlDb->GetNumberTableEntries(); iEntry++)
+		{
+		CXMLTableEntry* entry = iXmlDb->GetTableEntry(iEntry);
+
+		gMsg->Msg(_L("Table : [%S]"),&entry->GetTableName());
+		gMsg->Msg(_L("Table Entry ID = [%D]"),entry->GetEntryId());
+
+		for(TInt iParam = 0; iParam < entry->GetNumberParameters(); iParam++)
+			{
+			gMsg->Msg(_L(" [%S] = [%S]"),&entry->GetParameterName(iParam),&entry->GetParameterValue(iParam));
+			}
+		}
+	}
+
+bool CXMLContentHandler::IsTableKnown(const TDesC&    aRefTable)
+	{
+	TInt i = 0;
+	TPtrC actTableName = xmlTableArray[i];
+
+	while(actTableName.Compare(TPtrC(NO_MORE_RECORDS)) != 0 &&
+		  actTableName.Compare(aRefTable) != 0)
+		{
+		actTableName.Set(TPtrC(xmlTableArray[++i]));
+		}
+
+	if (aRefTable.Compare(actTableName) == 0)
+		{
+		return ETrue;
+		}
+
+	return EFalse;
+	}
+
+//----------------- CXMLTableEntry ----------------
+
+
+// Constructor for the CXMLTableEntry class
+CXMLTableEntry::CXMLTableEntry()
+: entryId(1)
+, iRecordID(0)
+, iDeleteFlag(EFalse)
+	{
+	__DECLARE_NAME(_S("CXMLTableEntry"));
+	}
+
+// Destructor for the CXMLTableEntry class
+CXMLTableEntry::~CXMLTableEntry()
+	{
+	paramName.ResetAndDestroy();
+	paramValue.ResetAndDestroy();
+
+	iLinkType.Close();
+	}
+
+CXMLTableEntry* CXMLTableEntry::NewL(const TDesC& aTableName)
+	{
+	CXMLTableEntry* p = new(ELeave) CXMLTableEntry;
+	CleanupStack::PushL(p);
+	p->ConstructL(aTableName);
+	CleanupStack::Pop(p);
+	return p;
+	}
+
+void CXMLTableEntry::ConstructL(const TDesC& aTableName)
+	{
+	tableName.Copy(aTableName);
+	}
+
+// Add a new pair of paramater name and value in this table entry
+void CXMLTableEntry::AddParameterL(const TBuf<MAX_BUFFER_LEN>& aParamName,
+								  const TBuf<MAX_BUFFER_LEN>& aParamValue)
+	{
+	TBuf<MAX_BUFFER_LEN>* name = new(ELeave) TBuf<MAX_BUFFER_LEN>;
+	name->Copy(aParamName);
+	paramName.Append(name);
+
+	TBuf<MAX_BUFFER_LEN>* value = new(ELeave) TBuf<MAX_BUFFER_LEN>;
+	value->Copy(aParamValue);
+	paramValue.Append(value);
+	}
+
+// Remove a parameter from the list
+void CXMLTableEntry::RemoveParameter(const TInt aIndex)
+	{
+	delete paramName[aIndex];
+	paramName.Remove(aIndex);
+	delete paramValue[aIndex];
+	paramValue.Remove(aIndex);
+	}
+
+// Set the value of a parameter given its index
+void CXMLTableEntry::SetParameterValue(const TInt aIndex,
+									   const TBuf<MAX_BUFFER_LEN>& aParamValue)
+	{
+	paramValue[aIndex]->Copy(aParamValue);
+	}
+
+// Rename a table entry parameter
+void CXMLTableEntry::RenameParameter(const TInt aIndex, const TBuf<MAX_BUFFER_LEN>& aNewName)
+	{
+	paramName[aIndex]->Copy(aNewName);
+	}
+
+
+
+
+//------------------ CXMLDatabase --------------------
+
+
+
+// Constructor for the CXMLDatabase class
+CXMLDatabase::CXMLDatabase()
+	{
+	__DECLARE_NAME(_S("CXMLDatabase"));
+	}
+
+// Destructor for the CXMLDatabase class
+CXMLDatabase::~CXMLDatabase()
+	{
+	tableEntries.ResetAndDestroy();
+	}
+
+CXMLDatabase* CXMLDatabase::NewL()
+	{
+	CXMLDatabase* p = new(ELeave) CXMLDatabase;
+	return p;
+	}
+
+// Add a table entry to the database given the pointer
+void CXMLDatabase::AddTableEntry(CXMLTableEntry* aEntry)
+	{
+	if(aEntry != NULL)
+		{
+		tableEntries.Append(aEntry);
+		}
+	}
+
+// Get a table entry from the database given its index which represents
+// its location in the database
+CXMLTableEntry* CXMLDatabase::GetTableEntry(const TInt aIndex)
+	{
+	if(aIndex >= 0 && aIndex < tableEntries.Count())
+		{
+		return tableEntries[aIndex];
+		}
+	else
+		{
+		return NULL;
+		}
+	}
+
+// Get the total number of table entries currently in the database
+TInt CXMLDatabase::GetNumberTableEntries() const
+	{
+	return tableEntries.Count();
+	}
+
+// Get the last table entry added to the database
+CXMLTableEntry* CXMLDatabase::GetLastTableEntry()
+	{
+	TInt index = tableEntries.Count();
+	if(index == 0)
+		{
+		return NULL;
+		}
+	else
+		{
+		return tableEntries[index-1];
+		}
+	}
+
+void CXMLDatabase::CheckDeletedElems()
+    {
+    TInt i = 0;
+
+    while (i < tableEntries.Count())
+        {
+        if (tableEntries[i]->GetDeleteFlag())
+            {
+            delete tableEntries[i];
+            tableEntries.Remove(i);
+            }
+        else
+            {
+            ++i;
+            }
+        }
+    }
+
+
+