omads/omadsextensions/datamod/src/nsmldatamodbase.cpp
changeset 0 dab8a81a92de
child 10 b922b9936679
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omads/omadsextensions/datamod/src/nsmldatamodbase.cpp	Mon Nov 23 14:46:41 2009 +0200
@@ -0,0 +1,724 @@
+/*
+* Copyright (c) 2005 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:  Versit data stripper and merger.
+*
+*/
+
+
+// INCLUDES
+#include "NSmlDataModBase.h"
+#include "nsmldebug.h"
+#include "nsmlconstants.h"
+
+#include <versit.h>
+#include <vcal.h>
+#include <vcard.h>
+#include <s32mem.h>
+#include <stringpool.h>
+#include <vtoken.h>
+#include <e32property.h>
+#include <DataSyncInternalPSKeys.h>
+
+//Fix to Remove the Bad Compiler Warnings
+#ifndef __WINS__
+// This lowers the unnecessary compiler warning (armv5) to remark.
+// "Warning:  #174-D: expression has no effect..." is caused by 
+// DBG_ARGS8 macro in no-debug builds.
+#pragma diag_remark 174
+#endif
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::~CNSmlDataModBase
+// Destructor.
+// ------------------------------------------------------------------------------------------------
+EXPORT_C CNSmlDataModBase::~CNSmlDataModBase()
+	{
+	}
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::SetOwnStoreFormat
+// Sets own database format.
+// ------------------------------------------------------------------------------------------------
+EXPORT_C void CNSmlDataModBase::SetOwnStoreFormat( CSmlDataStoreFormat& aOwnStoreFormat )
+	{
+	_DBG_FILE("CNSmlDataModBase::SetOwnStoreFormat(): begin");
+	iOwnStoreFormat = &aOwnStoreFormat;
+	_DBG_FILE("CNSmlDataModBase::SetOwnStoreFormat(): end");
+	}
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::SetPartnerStoreFormat
+// Sets remote database format.
+// ------------------------------------------------------------------------------------------------
+EXPORT_C void CNSmlDataModBase::SetPartnerStoreFormat( CSmlDataStoreFormat& aRemoteStoreFormat )
+	{
+	_DBG_FILE("CNSmlDataModBase::SetPartnerStoreFormat(): begin");
+	iRemoteStoreFormat = &aRemoteStoreFormat;
+	_DBG_FILE("CNSmlDataModBase::SetPartnerStoreFormat(): end");
+	}
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::SetUsedMimeType
+// Sets mime type that is used for sending and receiving. 
+// This method can be called separately before every item.
+// ------------------------------------------------------------------------------------------------
+EXPORT_C TInt CNSmlDataModBase::SetUsedMimeType( const RStringF aMimeType, const RStringF aMimeVersion )
+	{
+	_DBG_FILE("CNSmlDataModBase::SetUsedMimeTypeL(): begin");
+	iUsedRemoteMimeType = -1;
+	if ( !iRemoteStoreFormat )
+		{
+		_DBG_FILE("CNSmlDataModBase::SetUsedMimeTypeL() - Not Found: end");
+		return KErrNotFound;
+		}
+	else
+		{
+		for ( TInt i = 0; i < iRemoteStoreFormat->MimeFormatCount(); i++ )
+			{
+			if ( iRemoteStoreFormat->MimeFormat( i ).MimeType().DesC().Compare( aMimeType.DesC() ) == 0 )
+				{
+				if ( iRemoteStoreFormat->MimeFormat( i ).MimeVersion().DesC().Compare( aMimeVersion.DesC() ) == 0 )
+					{
+					iUsedRemoteMimeType = i;
+					iMimeType = iRemoteStoreFormat->MimeFormat( i ).MimeType();
+					iMimeVersion = iRemoteStoreFormat->MimeFormat( i ).MimeVersion();
+					_DBG_FILE("CNSmlDataModBase::SetUsedMimeTypeL() - Found: end");
+					return KErrNone;
+					}
+				}
+			}
+		}
+	_DBG_FILE("CNSmlDataModBase::SetUsedMimeTypeL() - Not Found: end");
+	return KErrNotFound;
+	}
+	
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::StripTxL
+// Strips data that is to be transmitted to the sync partner.
+// ------------------------------------------------------------------------------------------------
+EXPORT_C void CNSmlDataModBase::StripTxL( CBufBase& aItem )
+	{
+	_DBG_FILE("CNSmlDataModBase::StripTxL(): begin");
+	HBufC8* buf = HBufC8::NewLC(aItem.Size() * 2);
+	*buf = aItem.Ptr(0);
+	TPtr8 ptrBuf = buf->Des();
+
+	StripL(ptrBuf);
+
+	aItem.Reset();
+	aItem.InsertL(0, ptrBuf);
+	CleanupStack::PopAndDestroy(); // buf
+	_DBG_FILE("CNSmlDataModBase::StripTxL(): end");
+	}
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::MergeRxL
+// Merges received item with item in exported from the local database.
+// ------------------------------------------------------------------------------------------------
+EXPORT_C void CNSmlDataModBase::MergeRxL( CBufBase& aNewItem, CBufBase& aOldItem, TBool aFieldLevel )
+	{
+	_DBG_FILE("CNSmlDataModBase::MergeRxL(): begin");
+	if( NeedsMerge() )
+		{
+		HBufC8* b1 = HBufC8::NewLC(aNewItem.Size() + aOldItem.Size());
+		*b1 = aNewItem.Ptr(0);
+		TPtr8 ptrB1 = b1->Des();
+		TPtr8 p2 = aOldItem.Ptr(0);
+
+		MergeL( ptrB1, p2, aFieldLevel );
+
+		aNewItem.Reset();
+		aNewItem.InsertL(0, ptrB1);
+		CleanupStack::PopAndDestroy(); // b1
+		}
+	else if ( iUsedRemoteMimeType == -1 )
+		{
+		User::Leave( KErrNotFound );
+		}
+	_DBG_FILE("CNSmlDataModBase::MergeRxL(): end");
+	}
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::NeedsMerge
+// Checks whether merging is needed or not.
+// ------------------------------------------------------------------------------------------------
+EXPORT_C TBool CNSmlDataModBase::NeedsMerge()
+	{
+	_DBG_FILE("CNSmlDataModBase::NeedsMerge(): begin");
+	iUsedRemoteMimeType = -1;
+	if ( !iRemoteStoreFormat )
+		{
+		_DBG_FILE("CNSmlDataModBase::NeedsMerge() - EFalse: end");
+		return EFalse;
+		}
+	else
+		{
+		for ( TInt i = 0; i < iRemoteStoreFormat->MimeFormatCount(); i++ )
+			{
+			if ( iRemoteStoreFormat->MimeFormat( i ).MimeType().DesC().Compare( iMimeType.DesC() ) == 0 )
+				{
+				if ( iRemoteStoreFormat->MimeFormat( i ).MimeVersion().DesC().Compare( iMimeVersion.DesC() ) == 0 )
+					{
+					iUsedRemoteMimeType = i;
+					if ( iRemoteStoreFormat->MimeFormat( i ).PropertyCount() > 0 )
+						{
+						_DBG_FILE("CNSmlDataModBase::NeedsMerge() - ETrue: end");
+						return ETrue;
+						}
+					}
+				}
+			}
+		}
+	_DBG_FILE("CNSmlDataModBase::NeedsMerge() - EFalse: end");
+	return EFalse;
+	}
+	
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::CNSmlDataModBase
+// Basic constructor of class.
+// ------------------------------------------------------------------------------------------------
+CNSmlDataModBase::CNSmlDataModBase()
+	{
+	iUsedOwnMimeType = -1;
+	iUsedRemoteMimeType = -1;
+	}
+	
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::StripL
+// Strips data that is to be transmitted to the sync partner.
+// ------------------------------------------------------------------------------------------------
+void CNSmlDataModBase::StripL( TDes8& aItem )
+	{
+	_DBG_FILE("CNSmlDataModBase::StripL(): begin");
+	if ( !NeedsMerge() )
+		{
+		if ( iUsedRemoteMimeType == -1 )
+			{
+			User::Leave( KErrNotFound );
+			}
+		return;
+		}
+	TBool modified( EFalse );
+	CVersitParser* parser = ChildCreateParserLC();
+	RDesReadStream drs( aItem );
+	CleanupClosePushL( drs );
+	parser->InternalizeL( drs );
+
+	// Now we're ready to start analysis
+	CArrayPtr<CVersitParser>* entities = parser->ArrayOfEntities( EFalse );
+	if( entities )
+		{
+		for( TInt i = 0; i < entities->Count(); i++ )
+			{
+			StripEntityL( entities->At( i ), modified );
+			}
+		}
+	else
+		{
+		StripEntityL( parser, modified );
+		}
+
+	// Only update if anything was modified in process
+	if( modified )
+		{
+		aItem.Zero();
+		RDesWriteStream dws( aItem );
+		CleanupClosePushL( dws );
+		parser->ExternalizeL( dws );
+		dws.CommitL();
+		CleanupStack::PopAndDestroy(); // dws
+		}
+	CleanupStack::PopAndDestroy( 2 ); // drs, parser
+	_DBG_FILE("CNSmlDataModBase::StripL(): end");
+	}
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::StripEntityL
+// Strips data that is to be transmitted to the sync partner from entity.
+// ------------------------------------------------------------------------------------------------
+void CNSmlDataModBase::StripEntityL( CVersitParser* aEntity, TBool& aModified ) const
+	{
+	_DBG_FILE("CNSmlDataModBase::StripEntityL(): begin");
+	StripAllNotOnPartnerListL( aEntity, aModified, ETrue );
+	_DBG_FILE("CNSmlDataModBase::StripEntityL(): end");
+	}
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::StripAllOnPartnerListL
+// Strips all data from entity that is supported by remote server.
+// ------------------------------------------------------------------------------------------------
+void CNSmlDataModBase::StripAllOnPartnerListL( CVersitParser* aEntity, TBool& aModified, TBool aParamLevelCheck ) const
+	{
+    _DBG_FILE("CNSmlDataModBase::StripAllOnPartnerListL(): begin");
+
+    if( iRemoteStoreFormat->MimeFormat( iUsedRemoteMimeType ).PropertyCount() )
+        {
+        
+        // Check correct Data Sync protocol
+        TInt value( EDataSyncNotRunning );
+        TSmlProtocolVersion usedSyncProtocol( ESmlVersion1_2 );
+        TInt error = RProperty::Get( KPSUidDataSynchronizationInternalKeys,
+                                     KDataSyncStatus,
+                                     value );
+        if ( error == KErrNone &&
+             value == EDataSyncRunning )
+            {
+            usedSyncProtocol = ESmlVersion1_1_2;
+            }
+        
+        TBool wasModified( EFalse );
+
+        CArrayPtr<CParserProperty>* allProps = aEntity->ArrayOfProperties( EFalse );
+        for( TInt i = 0; i < allProps->Count(); ) // Variable i is not increased here because size of count might be changes during loop
+            {
+            const CParserProperty& ownProperty = *allProps->At( i );
+            CParserPropertyValue* ownValue = ownProperty.Value();
+
+            TBool removeMe( EFalse );
+            
+            for( TInt i2 = 0; i2 < iRemoteStoreFormat->MimeFormat( iUsedRemoteMimeType ).PropertyCount(); i2++ )
+                {
+                const CSmlDataProperty& remoteProperty = iRemoteStoreFormat->MimeFormat( iUsedRemoteMimeType ).Property( i2 );
+                if( !ownProperty.Name().Compare( remoteProperty.Field().Name().DesC() ) )
+                    {
+                    if( remoteProperty.ParamCount() > 0 && aParamLevelCheck )
+                        {
+                        if ( usedSyncProtocol == ESmlVersion1_1_2 )
+                            {
+                            for( TInt i3 = 0; i3 < remoteProperty.ParamCount(); i3++ )
+                                {
+                                if( ownProperty.Param( remoteProperty.Param( i3 ).Field().Name().DesC() ) )
+                                    {
+                                    removeMe = ETrue;
+                                    }
+                                }                           
+                            }
+                        else // ESmlVersion1_2
+                            {
+                            CArrayPtr<CParserParam>* ownerparamarray = ownProperty.ParamArray();
+                            if(ownerparamarray != NULL)
+                                {
+                                for(TInt ownerparam = 0; ownerparam < ownerparamarray->Count(); ownerparam++)
+                                    {
+                                    removeMe = EFalse;
+                                    const CParserParam& ownParam = *ownerparamarray->At( ownerparam );
+                                     TPtrC8 ownparamname = ownParam.Name();
+                                     TPtrC8 ownparamvalue = ownParam.Value();
+                                     if(ownparamvalue == _L8(""))
+                                        {
+                                         for(TInt remoteparam = 0; remoteparam < remoteProperty.ParamCount(); remoteparam++)
+                                            {
+                                            TDesC8 remoteparamname = remoteProperty.Param( remoteparam ).Field().Name().DesC();
+                                            const CSmlDataField& field = remoteProperty.Param( remoteparam ).Field();
+											if(field.EnumValueCount() > 0)
+												{
+	                                            for( TInt rmtenumcount = 0; rmtenumcount < field.EnumValueCount(); rmtenumcount++ )
+													{
+	                                                TPtrC8 rmtenumvalue = field.EnumValue( rmtenumcount ).DesC();
+													if( rmtenumvalue.Compare(ownparamname)== 0 )
+	                                                    {
+	                                                    removeMe = ETrue;
+														break;
+	                                                    }  
+	                                                } 
+												}
+											else
+												{
+												removeMe = ETrue;
+												break;
+												}
+                                            }
+                                        }
+                                     else
+                                        {
+										//Handling when the device supports VersitTokenType as "Encoding"    
+										if(ownparamname == KVersitTokenENCODING)
+											{
+											removeMe = ETrue;
+											}
+										else
+											{
+	                                         for(TInt remoteparam = 0; remoteparam < remoteProperty.ParamCount(); remoteparam++)
+	                                            {
+	                                            if(ownparamname.Compare(remoteProperty.Param( remoteparam ).Field().Name().DesC()) == 0)
+	                                                {
+	                                                const CSmlDataField& field = remoteProperty.Param( remoteparam ).Field();
+													if( field.EnumValueCount() > 0 )
+														{
+		                                                for( TInt rmtenumcount = 0; rmtenumcount < field.EnumValueCount(); rmtenumcount++ )
+		                                                    {
+		                                                     TPtrC8 rmtenumvalue = field.EnumValue( rmtenumcount ).DesC();
+		                                                     if( rmtenumvalue.Compare(ownparamvalue)== 0 )
+		                                                         {
+		                                                         removeMe = ETrue;
+																 break;
+		                                                         }  
+		                                                    } 
+														}
+													else
+														{
+														removeMe = ETrue;
+														break;
+														}
+	                                                }                                               
+	                                            }
+											}
+                                        }
+                                    	if( !removeMe )
+                                        {
+                                        	break;
+                                        }	    
+                                    } 
+                                }
+                            else
+                                {
+                                removeMe = ETrue;
+                                }
+                            }
+                        }
+                    else
+                        {
+                        removeMe = ETrue;
+                        }
+
+                    if( removeMe )
+                        {
+                        break;
+                        }
+                    }
+                }
+            if( removeMe )
+                {
+                #ifdef __NSML_DEBUG__
+                    TPtrC8 pn( ownProperty.Name() );
+                    DBG_ARGS8(_S8("CNSmlDataModBase::StripAllOnPartnerListL(): Dropping %S"), &pn);
+                #endif // __NSML_DEBUG__
+                delete allProps->At( i );
+                allProps->Delete( i );
+                wasModified = ETrue;
+                aModified = ETrue;
+                }
+            else
+                {
+                #ifdef __NSML_DEBUG__
+                    TPtrC8 pn( ownProperty.Name() );
+                    DBG_ARGS8(_S8("CNSmlDataModBase::StripAllOnPartnerListL(): NOT dropping %S"), &pn);
+                #endif // __NSML_DEBUG__
+                i++;
+                }
+            }
+        // can't use aModified as that may have been set earlier!
+        if( wasModified )
+            {
+            allProps->Compress();
+            }
+        }
+    _DBG_FILE("CNSmlDataModBase::StripAllOnPartnerListL(): end");
+    }
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::StripAllNotOnPartnerListL
+// Strips all data from entity that is not supported by remote server.
+// ------------------------------------------------------------------------------------------------
+void CNSmlDataModBase::StripAllNotOnPartnerListL( CVersitParser* aEntity, TBool& aModified, TBool aParamLevelCheck ) const
+	{
+    _DBG_FILE("CNSmlDataModBase::StripAllNotOnPartnerListL(): begin");
+    TInt remotepropertycount = iRemoteStoreFormat->MimeFormat( iUsedRemoteMimeType ).PropertyCount();
+    if( iRemoteStoreFormat->MimeFormat( iUsedRemoteMimeType ).PropertyCount() )
+        {
+        
+        // Check correct Data Sync protocol
+        TInt value( EDataSyncNotRunning );
+        TSmlProtocolVersion usedSyncProtocol( ESmlVersion1_2 );
+        TInt error = RProperty::Get( KPSUidDataSynchronizationInternalKeys,
+                                     KDataSyncStatus,
+                                     value );
+        if ( error == KErrNone &&
+             value == EDataSyncRunning )
+            {
+            usedSyncProtocol = ESmlVersion1_1_2;
+            }
+
+        TBool wasModified( EFalse );
+
+        CArrayPtr<CParserProperty>* allProps = aEntity->ArrayOfProperties( EFalse );
+        for( TInt i = 0; i < allProps->Count(); ) // Variable i is not increased here because size of count might be changes during loop
+            {
+            const CParserProperty& ownProperty = *allProps->At( i );
+            TBuf8<30> name = ownProperty.Name();
+            CParserPropertyValue* ownValue = ownProperty.Value();
+
+            TBool removeMe( ETrue );
+            
+            for( TInt i2 = 0; i2 < iRemoteStoreFormat->MimeFormat( iUsedRemoteMimeType ).PropertyCount(); i2++ )
+                {
+                const CSmlDataProperty& remoteProperty = iRemoteStoreFormat->MimeFormat( iUsedRemoteMimeType ).Property( i2 );
+                TPtrC8 remotename = remoteProperty.Field().Name().DesC();
+                if( !ownProperty.Name().Compare( remoteProperty.Field().Name().DesC() ) )
+                    {
+                    TInt remoteparamcount = remoteProperty.ParamCount();
+                    if( remoteProperty.ParamCount() > 0 && aParamLevelCheck )
+                        {
+                        if ( usedSyncProtocol == ESmlVersion1_1_2 )
+                            {
+                            const CParserProperty* p = allProps->At( i );
+                            TInt entityParamCount = (( CNSmlProperty* )p)->ParamCount();
+                            if( entityParamCount > 0)
+                            {
+                            for( TInt i3 = 0; i3 < remoteProperty.ParamCount(); i3++ )
+                                {
+                                TPtrC8 remoteparamname = remoteProperty.Param( i3 ).Field().Name().DesC();
+                                if( ownProperty.Param( remoteProperty.Param( i3 ).Field().Name().DesC() ) )
+                                    {
+                                    removeMe = EFalse;
+                                    }
+                                }                           
+                            }
+                            else
+                            {
+                                removeMe = EFalse;
+                            }
+                            }
+                        else // ESmlVersion1_2
+                            {
+                            CArrayPtr<CParserParam>* ownerparamarray = ownProperty.ParamArray();
+                            if(ownerparamarray != NULL)
+                                {
+                                for(TInt ownerparam = 0; ownerparam < ownerparamarray->Count(); ownerparam++)
+                                    {
+									removeMe = ETrue;
+                                    const CParserParam& ownParam = *ownerparamarray->At( ownerparam );
+                                     TPtrC8 ownparamname = ownParam.Name();
+                                     TPtrC8 ownparamvalue = ownParam.Value();
+                                     if(ownparamvalue == _L8(""))
+                                        {
+                                         for(TInt remoteparam = 0; remoteparam < remoteProperty.ParamCount(); remoteparam++)
+                                            {
+                                            TDesC8 remoteparamname = remoteProperty.Param( remoteparam ).Field().Name().DesC();
+                                            const CSmlDataField& field = remoteProperty.Param( remoteparam ).Field();
+											if( field.EnumValueCount() > 0)
+												{
+												for( TInt rmtenumcount = 0; rmtenumcount < field.EnumValueCount(); rmtenumcount++ )
+													{
+													TPtrC8 rmtenumvalue = field.EnumValue( rmtenumcount ).DesC();
+													if( rmtenumvalue.Compare(ownparamname)== 0 )
+														{
+														removeMe = EFalse;
+														break;
+														}
+													} 
+												}
+											else
+												{
+												removeMe = EFalse;
+												break;
+												}											
+                                            }
+                                        }
+                                     else
+                                        {
+										//Handling when the device supports VersitTokenType as "Encoding"    
+										if(ownparamname == KVersitTokenENCODING)
+											{
+											removeMe = EFalse;
+											}
+										else
+											{
+	                                         for(TInt remoteparam = 0; remoteparam < remoteProperty.ParamCount(); remoteparam++)
+	                                            {
+	                                            TDesC8 remoteparamname = remoteProperty.Param( remoteparam ).Field().Name().DesC();
+	                                            if(ownparamname.Compare(remoteProperty.Param( remoteparam ).Field().Name().DesC()) == 0)
+	                                                {
+	                                                const CSmlDataField& field = remoteProperty.Param( remoteparam ).Field();
+													if( field.EnumValueCount() > 0)
+														{
+		                                                for( TInt rmtenumcount = 0; rmtenumcount < field.EnumValueCount(); rmtenumcount++ )
+		                                                    {
+		                                                     TPtrC8 rmtenumvalue = field.EnumValue( rmtenumcount ).DesC();
+		                                                     if( rmtenumvalue.Compare(ownparamvalue)== 0 )
+		                                                         {
+		                                                         removeMe = EFalse;
+																 break;
+		                                                         }  
+		                                                    }
+														}
+													else
+														{
+														removeMe = EFalse;
+														break;
+														}
+	                                                }
+												}
+											}                                 
+                                        }
+                                        if( removeMe )
+                                        {
+                                        	break;
+                                        }	
+                                    } 
+                                }
+                            else
+                                {
+                                removeMe = EFalse;
+                                }
+                            }
+                        }
+                    else
+                        {
+                        removeMe = EFalse;
+                        }
+
+                    if( !removeMe )
+                        {
+                        break;
+                        }
+                    }
+                }
+            if( removeMe )
+                {
+                #ifdef __NSML_DEBUG__
+                    TPtrC8 pn( ownProperty.Name() );
+                    DBG_ARGS8(_S8("CNSmlDataModBase::StripAllNotOnPartnerListL(): Dropping %S"), &pn);
+                #endif // __NSML_DEBUG__
+                delete allProps->At( i );
+                allProps->Delete( i );
+                wasModified = ETrue;
+                aModified = ETrue;
+                }
+            else
+                {
+                #ifdef __NSML_DEBUG__
+                    TPtrC8 pn( ownProperty.Name() );
+                    DBG_ARGS8(_S8("CNSmlDataModBase::StripAllNotOnPartnerListL(): NOT dropping %S"), &pn);
+                #endif // __NSML_DEBUG__
+                i++;
+                }
+            }
+        // can't use aModified as that may have been set earlier!
+        if( wasModified )
+            {
+            allProps->Compress();
+            }
+        }
+    _DBG_FILE("CNSmlDataModBase::StripAllNotOnPartnerListL(): end");
+    }
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::MergeL
+// Merges data from old item to new item.
+// ------------------------------------------------------------------------------------------------
+void CNSmlDataModBase::MergeL( TDes8& aNewItem, const TDesC8& aOldItem,TBool aFieldLevel )
+	{
+	TBool modified( EFalse );
+	CVersitParser* newItemParser = ChildCreateParserLC();
+	RDesReadStream newStream( aNewItem );
+	CleanupClosePushL( newStream );
+	newItemParser->InternalizeL( newStream );
+	CVersitParser* oldItemParser = ChildCreateParserLC();
+	RDesReadStream oldStream( aOldItem );
+	CleanupClosePushL( oldStream );
+	oldItemParser->InternalizeL( oldStream );
+
+	// Now we're ready to start analysis
+	CArrayPtr<CVersitParser>* newEntities = newItemParser->ArrayOfEntities( EFalse );
+	CArrayPtr<CVersitParser>* oldEntities = oldItemParser->ArrayOfEntities( ETrue );
+
+	if( newEntities && oldEntities )
+		{
+		CleanupPtrArrayPushL( oldEntities );
+		for( TInt i = 0; ( i < newEntities->Count() ) && ( i < oldEntities->Count() ); i++ )
+			{
+			MergeEntityL( newEntities->At( i ), oldEntities->At( i ), modified, aFieldLevel );
+			}
+		CleanupStack::PopAndDestroy(); // oldEntities
+		}
+	else
+		{
+		MergeEntityL( newItemParser, oldItemParser, modified, aFieldLevel );
+		}
+
+	// Only update if anything was modified in process
+	if ( modified )
+		{
+		aNewItem.Zero();
+		RDesWriteStream dws( aNewItem );
+		CleanupClosePushL( dws );
+		newItemParser->ExternalizeL( dws );
+		dws.CommitL();
+		CleanupStack::PopAndDestroy(); // dws
+		}
+
+	CleanupStack::PopAndDestroy( 4 ); // oldStream, oldItemParser, newStream, newItemParser
+	}
+
+// ------------------------------------------------------------------------------------------------
+// CNSmlDataModBase::MergeEntityL
+// Merges data from old entity to new entity.
+// ------------------------------------------------------------------------------------------------
+void CNSmlDataModBase::MergeEntityL( CVersitParser* aNewEntity, CVersitParser* aOldEntity, TBool& aModified, TBool aFieldLevel ) const
+	{
+	_DBG_FILE("CNSmlDataModBase::MergeEntityL(): begin");
+
+	// Remove all data that was not supposed to be supported by the partner but
+	// it was still sent to us.
+	StripAllNotOnPartnerListL( aNewEntity, aModified );
+	
+	// Remove all properties from old item that are supported by remote server.
+	// If it is field level then old this is not done.
+	if( !aFieldLevel )
+		{
+		StripAllOnPartnerListL( aOldEntity, aModified, ETrue );
+		CArrayPtr<CParserProperty>* mergeProps = aOldEntity->ArrayOfProperties( ETrue );
+		if( mergeProps )
+		    {
+			CleanupStack::PushL( mergeProps );
+			
+			for( TInt i = 0; i < mergeProps->Count(); i++ )
+				{
+				aNewEntity->AddPropertyL( mergeProps->At( i ), ETrue );
+				}
+			
+			CleanupStack::PopAndDestroy(); // mergeProps
+		    }
+		}
+	else
+		{
+		User::Leave( KErrNotSupported );
+		}
+	
+	#ifdef __NSML_DEBUG__
+		CArrayPtr<CParserProperty>* props = aNewEntity->ArrayOfProperties( EFalse );
+		for( TInt i = 0; i < props->Count(); i++ )
+			{
+			TBuf8<512> b;
+			const CParserProperty* p = props->At( i );
+			b = p->Name();
+			const CArrayPtr<CParserParam>* pa = ( ( CNSmlProperty* )p )->Parameters();
+			if( pa )
+				{
+				for( TInt i2 = 0; i2 < pa->Count(); i2++ )
+					{
+					b.Append( _L8(":") );
+					b.Append( pa->At( i2 )->Name() );
+					}
+				}
+			DBG_ARGS8(_S8("CNSmlDataModBase::MergeEntityL(): %S"), &b);
+			}
+	#endif // __NSML_DEBUG__
+	_DBG_FILE("CNSmlDataModBase::MergeEntityL(): end");
+	}
+
+// End of file