--- /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