diff -r 2691f6aa1921 -r e1de7d03f843 omads/omadsextensions/adapters/agenda/src/nsmlagendadatastore.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omads/omadsextensions/adapters/agenda/src/nsmlagendadatastore.cpp Fri Apr 16 14:53:26 2010 +0300 @@ -0,0 +1,1770 @@ +/* +* 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: DS agenda data store +* +*/ + + + +// INCLUDES +#include "nsmldebug.h" +#include "nsmlagendadatastore.h" +#include "nsmlagendadataprovider.h" +#include "nsmlchangefinder.h" +#include "NSmlDataModBase.h" +#include "nsmlagendadefines.hrh" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ============================== +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::CNSmlAgendaDataStore +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CNSmlAgendaDataStore::CNSmlAgendaDataStore() : + iKey( TKeyArrayFix( _FOFF( TNSmlSnapshotItem, ItemId() ), ECmpTInt ) ), + iPos( -1 ), + iHasHistory( EFalse ), + iModificationCount( KNSmlCompactAfterChanges ), + iState( ENSmlClosed ), + iSnapshotRegistered( EFalse ), + iDrive( -1 ), + iReplaceItemId( -1 ), + iRXEntryType( ENSmlNotSet ), + iTXEntryType( ENSmlNotSet ) + { + _DBG_FILE("CNSmlAgendaDataStore::CNSmlAgendaDataStore(): BEGIN"); + _DBG_FILE("CNSmlAgendaDataStore::CNSmlAgendaDataStore(): END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::ConstructL() + { + _DBG_FILE("CNSmlAgendaDataStore::ConstructL: BEGIN"); + + iStringPool.OpenL(); + User::LeaveIfError( iRfs.Connect() ); + + iDataMod = new ( ELeave ) CNSmlVCalMod(); + + iNewUids = new ( ELeave ) CNSmlDataItemUidSet(); + iDeletedUids = new ( ELeave ) CNSmlDataItemUidSet(); + iSoftDeletedUids = new ( ELeave ) CNSmlDataItemUidSet(); + iMovedUids = new ( ELeave ) CNSmlDataItemUidSet(); + iReplacedUids = new ( ELeave ) CNSmlDataItemUidSet(); + + iDefaultStoreName = HBufC::NewL( KNSmlDefaultStoreNameMaxSize ); + + iVersitTlsData = &CVersitTlsData::VersitTlsDataL(); + // Create CalSession and CalEntryView instances + iVCalSession = CCalSession::NewL(); + + TPtr obptr = iDefaultStoreName->Des(); + obptr = iVCalSession->DefaultFileNameL(); + + iOwnFormat = DoOwnStoreFormatL(); + iDataMod->SetOwnStoreFormat( *iOwnFormat ); + + iInterimUtils = CCalenInterimUtils2::NewL(); + + _DBG_FILE("CNSmlAgendaDataStore::ConstructL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CNSmlAgendaDataStore* CNSmlAgendaDataStore::NewL() + { + _DBG_FILE("CNSmlAgendaDataStore::NewL: BEGIN"); + + CNSmlAgendaDataStore* self = new ( ELeave ) CNSmlAgendaDataStore(); + CleanupStack::PushL( self ); + + self->ConstructL(); + CleanupStack::Pop(); // self + + _DBG_FILE("CNSmlAgendaDataStore::NewL: END"); + return self; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::~CNSmlAgendaDataStore +// Destructor. +// ----------------------------------------------------------------------------- +// +CNSmlAgendaDataStore::~CNSmlAgendaDataStore() + { + _DBG_FILE("CNSmlAgendaDataStore::~CNSmlAgendaDataStore(): BEGIN"); + + // Enable notifications + TInt error( KErrNone ); + if ( iVCalSession ) + { + TRAP_IGNORE( iVCalSession->EnablePubSubNotificationsL() ); + TRAP_IGNORE( iVCalSession->EnableChangeBroadcast() ); + } + + delete iOwnFormat; + iRfs.Close(); + iStringPool.Close(); + + if ( iChangeFinder ) + { + TRAP( error, iChangeFinder->CloseL() ); + } + if (iVersitTlsData) + { + iVersitTlsData->VersitTlsDataClose(); + } + delete iChangeFinder; + delete iNewUids; + delete iDeletedUids; + delete iSoftDeletedUids; + delete iMovedUids; + delete iReplacedUids; + + delete iDefaultStoreName; + delete iOpenedStoreName; + delete iDataMod; + delete iItemData; + + delete iAgendaProgressview; + + delete iImporter; + delete iExporter; + + delete iEntryView; + delete iVCalSession; + delete iInterimUtils; + + + // REComSession::FinalClose(); + + _DBG_FILE("CNSmlAgendaDataStore::~CNSmlAgendaDataStore(): END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoOpenL +// Open calendar database for access. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoOpenL( const TDesC& aStoreName, + MSmlSyncRelationship& aContext, TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoOpenL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + if ( iState != ENSmlClosed ) + { + User::RequestComplete( iCallerStatus, KErrInUse ); + return; + } + + if( RFs::CharToDrive( aStoreName[0], iDrive ) != KErrNone ) + { + RFs::CharToDrive( KNSmlDriveC()[0], iDrive ); + } + + // Open database + TInt err( KErrNone ); + if ( aStoreName == KNSmlAgendaStoreNameForDefaultDB ) + { + TRAP( err, iVCalSession->OpenL( *iDefaultStoreName ) ); + } + else + { + TRAP( err, iVCalSession->OpenL( aStoreName ) ); + } + if ( err ) + { + User::RequestComplete( iCallerStatus, err ); + return; + } + + // Disable notifications + TRAP_IGNORE( iVCalSession->DisablePubSubNotificationsL() ); + TRAP_IGNORE( iVCalSession->DisableChangeBroadcast() ); + + if ( iOpenedStoreName ) + { + delete iOpenedStoreName; + iOpenedStoreName = NULL; + } + iOpenedStoreName = aStoreName.AllocL(); + + // Initialize some member variables + // Create importer and exporter + iImporter = CCalenImporter::NewL( *iVCalSession ); + iExporter = CCalenExporter::NewL( *iVCalSession ); + + // Progress view + iAgendaProgressview = CNSmlAgendaProgressview::NewL(); + + iEntryView = CCalEntryView::NewL( *iVCalSession, *iAgendaProgressview ); + CActiveScheduler::Start(); + TInt completedStatus = iAgendaProgressview->GetCompletedStatus(); + if ( completedStatus != KErrNone ) + { + User::RequestComplete( iCallerStatus, completedStatus ); + return; + } + + if ( iChangeFinder ) + { + iChangeFinder->CloseL(); + delete iChangeFinder; + iChangeFinder = NULL; + } + iChangeFinder = CNSmlChangeFinder::NewL( aContext, iKey, iHasHistory, + KNSmlAgendaAdapterImplUid ); + + // Get ID of database + iVCalSession->FileIdL( iOpenedStoreId ); + + if( !iSnapshotRegistered ) + { + RegisterSnapshotL(); + } + + iState = ENSmlOpenAndWaiting; + User::RequestComplete( iCallerStatus, err ); + + _DBG_FILE("CNSmlAgendaDataStore::DoOpenL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoCancelRequest +// Set internal module state to previous state. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoCancelRequest() + { + _DBG_FILE("CNSmlAgendaDataStore::DoCancelRequest: BEGIN"); + if ( iState == ENSmlOpenAndWaiting ) + { + iState = ENSmlClosed; + } + else + { + iState = ENSmlOpenAndWaiting; + } + _DBG_FILE("CNSmlAgendaDataStore::DoCancelRequest: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoStoreName +// Returns previously opened database name. +// ----------------------------------------------------------------------------- +// +const TDesC& CNSmlAgendaDataStore::DoStoreName() const + { + _DBG_FILE("CNSmlAgendaDataStore::DoStoreName: BEGIN"); + _DBG_FILE("CNSmlAgendaDataStore::DoStoreName: END"); + return *iOpenedStoreName; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoBeginTransactionL +// Not supported. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoBeginTransactionL() + { + _DBG_FILE("CNSmlAgendaDataStore::DoBeginTransactionL: BEGIN"); + User::Leave( KErrNotSupported ); + _DBG_FILE("CNSmlAgendaDataStore::DoBeginTransactionL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoCommitTransactionL +// Not supported. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoCommitTransactionL( TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitTransactionL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + User::RequestComplete( iCallerStatus, KErrNotSupported ); + _DBG_FILE("CNSmlAgendaDataStore::DoCommitTransactionL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoRevertTransaction +// Not supported. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoRevertTransaction( TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoRevertTransaction: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + User::RequestComplete( iCallerStatus, KErrNotSupported ); + _DBG_FILE("CNSmlAgendaDataStore::DoRevertTransaction: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoBeginBatchL +// Not supported. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoBeginBatchL() + { + _DBG_FILE("CNSmlAgendaDataStore::DoBeginBatchL: BEGIN"); + User::Leave( KErrNotSupported ); + _DBG_FILE("CNSmlAgendaDataStore::DoBeginBatchL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoCommitBatchL +// Not supported. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoCommitBatchL( RArray& /*aResultArray*/, + TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitBatchL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + User::RequestComplete( iCallerStatus, KErrNotSupported ); + _DBG_FILE("CNSmlAgendaDataStore::DoCommitBatchL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoCancelBatch +// Not supported. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoCancelBatch() + { + _DBG_FILE("CNSmlAgendaDataStore::DoCancelBatch: BEGIN"); + // Nothing to do + _DBG_FILE("CNSmlAgendaDataStore::DoCancelBatch: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoSetRemoteStoreFormatL +// Set SyncML Remote Server data store format. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoSetRemoteStoreFormatL( + const CSmlDataStoreFormat& aServerDataStoreFormat ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoSetRemoteStoreFormatL: BEGIN"); + + if ( iOwnFormat ) + { + delete iOwnFormat; + iOwnFormat = NULL; + } + + iOwnFormat = DoOwnStoreFormatL(); + iDataMod->SetOwnStoreFormat( *iOwnFormat ); + + iDataMod->SetPartnerStoreFormat( ( CSmlDataStoreFormat& ) + aServerDataStoreFormat ); + + // Check which calendar type (vCal/iCal) is used + // If server supports iCal then it is used + // Otherwise vCal is used + TInt returnValue( KErrNotSupported ); + +#ifdef __NSML_USE_ICAL_FEATURE + + _DBG_FILE("CNSmlAgendaDataStore::DoSetRemoteStoreFormatL: Support iCal"); + returnValue = iDataMod->SetUsedMimeType( + iOwnFormat->MimeFormat( 1 ).MimeType(), + iOwnFormat->MimeFormat( 1 ).MimeVersion() ); + +#endif // __NSML_USE_ICAL_FEATURE + + if ( returnValue == KErrNone ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoSetRemoteStoreFormatL: Sets iCal"); + iRXEntryType = ENSmlICal; + iTXEntryType = ENSmlICal; + } + else + { + _DBG_FILE("CNSmlAgendaDataStore::DoSetRemoteStoreFormatL: Support vCal"); + returnValue = iDataMod->SetUsedMimeType( + iOwnFormat->MimeFormat( 0 ).MimeType(), + iOwnFormat->MimeFormat( 0 ).MimeVersion() ); + if ( returnValue == KErrNone ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoSetRemoteStoreFormatL: Sets vCal"); + iRXEntryType = ENSmlVCal; + iTXEntryType = ENSmlVCal; + } + } + if ( iRXEntryType == ENSmlNotSet || iTXEntryType == ENSmlNotSet ) + { + // Leave if server does not support either vCal or iCal + _DBG_FILE("CNSmlAgendaDataStore::DoSetRemoteStoreFormatL: MimeType Not supported"); + User::Leave( KErrNotFound ); + } + + _DBG_FILE("CNSmlAgendaDataStore::DoSetRemoteStoreFormatL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoSetRemoteMaxObjectSize +// Set SyncML Remote Server maximum object size. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoSetRemoteMaxObjectSize( TInt aServerMaxObjectSize ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoSetRemoteMaxObjectSize: BEGIN"); + iServerMaxObjectSize = aServerMaxObjectSize; + _DBG_FILE("CNSmlAgendaDataStore::DoSetRemoteMaxObjectSize: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoMaxObjectSize +// Set SyncML Component maximum object size. +// ----------------------------------------------------------------------------- +// +TInt CNSmlAgendaDataStore::DoMaxObjectSize() const + { + _DBG_FILE("CNSmlAgendaDataStore::DoMaxObjectSize: BEGIN"); + _DBG_FILE("CNSmlAgendaDataStore::DoMaxObjectSize - Default: END"); + return KNSmlAgendaOwnMaxObjectSize; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoOpenItemL +// Open calendar item for reading. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoOpenItemL( TSmlDbItemUid aUid, TBool& aFieldChange, + TInt& aSize, TSmlDbItemUid& /*aParent*/, TDes8& aMimeType, + TDes8& aMimeVer, TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoOpenItemL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + if ( iState != ENSmlOpenAndWaiting ) + { + User::RequestComplete( iCallerStatus, KErrNotReady ); + return; + } + + iReplaceItemId = aUid; + + CCalEntry* entry = NULL; + TInt err( KErrNone ); + TRAP( err, entry = iEntryView->FetchL( aUid ) ); + CleanupStack::PushL( entry ); + + if ( err || !entry ) + { + CleanupStack::PopAndDestroy( entry ); // entry + User::RequestComplete( iCallerStatus, KErrNotFound ); + return; + } + + if ( !iSnapshotRegistered ) + { + RegisterSnapshotL(); + } + delete iItemData; + iItemData = NULL; + iItemData = CBufFlat::NewL( KNSmlItemDataExpandSize ); + + RBufWriteStream writeStream( *iItemData ); + writeStream.PushL(); + + // Export item from database + if ( iTXEntryType == ENSmlICal ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoOpenItemL: Export - iCal DB"); + iExporter->ExportICalL( *entry, writeStream ); + aMimeType = iOwnFormat->MimeFormat( 1 ).MimeType().DesC(); + aMimeVer = iOwnFormat->MimeFormat( 1 ).MimeVersion().DesC(); + } + else if ( iTXEntryType == ENSmlVCal ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoOpenItemL: Export - vCal DB"); + iExporter->ExportVCalL( *entry, writeStream ); + aMimeType = iOwnFormat->MimeFormat( 0 ).MimeType().DesC(); + aMimeVer = iOwnFormat->MimeFormat( 0 ).MimeVersion().DesC(); + } + else + { + _DBG_FILE("CNSmlAgendaDataStore::DoOpenItemL: Export - DB Not Supported"); + CleanupStack::PopAndDestroy( 2 ); // writeStream, entry + User::RequestComplete( iCallerStatus, KErrNotSupported ); + return; + } + + writeStream.CommitL(); + iItemData->Compress(); + iPos = 0; + +#ifdef __NSML_MORE_DEBUG_FOR_ITEMS__ + + DBG_DUMP( ( void* )iItemData->Ptr( 0 ).Ptr(), iItemData->Size(), + _S8( "Item from database:" ) ); + +#endif // __NSML_MORE_DEBUG_FOR_ITEMS__ + + + iDataMod->StripTxL( *iItemData ); + CleanupStack::PopAndDestroy( 2 ); // writeStream, entry + +#ifdef __NSML_MORE_DEBUG_FOR_ITEMS__ + + DBG_DUMP( ( void* )iItemData->Ptr( 0 ).Ptr(), iItemData->Size(), + _S8( "Item from database after strip:" ) ); + +#endif // __NSML_MORE_DEBUG_FOR_ITEMS__ + + aFieldChange = EFalse; + aSize = iItemData->Size(); + + iState = ENSmlItemOpen; + + if ( iServerMaxObjectSize == 0 || aSize <= iServerMaxObjectSize ) + { + User::RequestComplete( iCallerStatus, KErrNone ); + } + else + { + User::RequestComplete( iCallerStatus, KErrTooBig ); + } + + _DBG_FILE("CNSmlAgendaDataStore::DoOpenItemL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoCreateItemL +// Prepare item data for writing to database. WriteItemL() writes item's data as +// buffered. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoCreateItemL( TSmlDbItemUid& aUid, TInt aSize, + TSmlDbItemUid /*aParent*/, const TDesC8& aMimeType, + const TDesC8& /*aMimeVer*/, TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCreateItemL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + iAddItemId = &aUid; + + if ( iState != ENSmlOpenAndWaiting ) + { + User::RequestComplete( iCallerStatus, KErrNotReady ); + _DBG_FILE("CNSmlAgendaDataStore::DoCreateItemL - KErrNotReady: END"); + return; + } + + if ( KNSmlAgendaOwnMaxObjectSize < aSize ) + { + User::RequestComplete( iCallerStatus, KErrTooBig ); + _DBG_FILE("CNSmlAgendaDataStore::DoCreateItemL - KErrTooBig: END"); + return; + } + + if( SysUtil::DiskSpaceBelowCriticalLevelL( &iRfs, aSize, iDrive ) ) + { + User::RequestComplete( iCallerStatus, KErrDiskFull ); + _DBG_FILE("CNSmlAgendaDataStore::DoCreateItemL - KErrDiskFull: END"); + return; + } + + // Check if MIME type of new item is supported + TBool mimeFound( EFalse ); + // vCal + if ( iOwnFormat->MimeFormat( 0 ).MimeType().DesC().Compare( aMimeType ) + == 0 ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCreateItemL: received vCal"); + mimeFound = ETrue; + iRXEntryType = ENSmlVCal; + } + +#ifdef __NSML_USE_ICAL_FEATURE + + // iCal + else if ( iOwnFormat->MimeFormat( 1 ).MimeType().DesC().Compare( aMimeType ) + == 0 ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCreateItemL: received iCal"); + mimeFound = ETrue; + iRXEntryType = ENSmlICal; + } + +#endif // __NSML_USE_ICAL_FEATURE + + // Else use original iRXEntryType + else + { + _DBG_FILE("CNSmlAgendaDataStore::DoCreateItemL: \ + mime type not received"); + iRXEntryType = iTXEntryType; + } + + if ( !mimeFound ) + { + User::RequestComplete( iCallerStatus, KErrNotSupported ); + _DBG_FILE("CNSmlAgendaDataStore::DoCreateItemL -KErrNotSupported: END"); + return; + } + + if( !iSnapshotRegistered ) + { + RegisterSnapshotL(); + } + delete iItemData; + iItemData = NULL; + iItemData = CBufFlat::NewL( KNSmlItemDataExpandSize ); + iPos = 0; + + iState = ENSmlItemCreating; + User::RequestComplete( iCallerStatus, KErrNone ); + _DBG_FILE("CNSmlAgendaDataStore::DoCreateItemL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoReplaceItemL +// Prepare item data for writing and replacing item in database. WriteItemL() +// writes item's data as buffered. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoReplaceItemL( TSmlDbItemUid aUid, TInt aSize, + TSmlDbItemUid /*aParent*/, TBool aFieldChange, + TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoReplaceItemL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + + if ( iState != ENSmlOpenAndWaiting ) + { + User::RequestComplete( iCallerStatus, KErrNotReady ); + _DBG_FILE("CNSmlAgendaDataStore::DoReplaceItemL - KErrNotReady: END"); + return; + } + + if ( KNSmlAgendaOwnMaxObjectSize < aSize ) + { + User::RequestComplete( iCallerStatus, KErrTooBig ); + _DBG_FILE("CNSmlAgendaDataStore::DoReplaceItemL - KErrTooBig: END"); + return; + } + + if ( aFieldChange ) + { + User::RequestComplete( iCallerStatus, KErrNotSupported ); + _DBG_FILE("CNSmlAgendaDataStore::DoReplaceItemL \ + - KErrNotSupported: END"); + return; + } + if ( SysUtil::DiskSpaceBelowCriticalLevelL( &iRfs, aSize, iDrive ) ) + { + User::RequestComplete( iCallerStatus, KErrDiskFull ); + _DBG_FILE("CNSmlAgendaDataStore::DoReplaceItemL - KErrDiskFull: END"); + return; + } + + iReplaceItemId = aUid; + + CCalEntry* entry = NULL; + TInt err( KErrNone ); + TRAP( err, entry = iEntryView->FetchL( aUid ) ); + CleanupStack::PushL( entry ); + + if ( !entry || err == KErrNotFound ) + { + CleanupStack::PopAndDestroy( entry ); // entry + User::RequestComplete( iCallerStatus, KErrNotFound ); + _DBG_FILE("CNSmlAgendaDataStore::DoReplaceItemL - KErrNotFound: END"); + return; + } + else if ( err ) + { + CleanupStack::PopAndDestroy( entry ); // entry + User::RequestComplete( iCallerStatus, err ); + _DBG_FILE("CNSmlAgendaDataStore::DoReplaceItemL - Error: END"); + return; + } + + CleanupStack::PopAndDestroy( entry ); // entry + + if ( !iSnapshotRegistered ) + { + RegisterSnapshotL(); + } + + delete iItemData; + iItemData = NULL; + iItemData = CBufFlat::NewL( KNSmlItemDataExpandSize ); + iPos = 0; + iReplaceItemId = aUid; + + iState = ENSmlItemUpdating; + User::RequestComplete( iCallerStatus, KErrNone ); + _DBG_FILE("CNSmlAgendaDataStore::DoReplaceItemL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoReadItemL +// Read item data to given buffer. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoReadItemL( TDes8& aBuffer ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoReadItemL: BEGIN"); + if ( iState != ENSmlItemOpen || !iItemData ) + { + iPos = -1; + User::Leave( KErrNotReady ); + } + + if ( iPos == -1 ) + { + User::Leave( KErrEof ); + } + + if ( aBuffer.Size() < iItemData->Size() - iPos ) + { + iItemData->Read( iPos, aBuffer ); + iPos += aBuffer.Size(); + } + else + { + iItemData->Read( iPos, aBuffer, iItemData->Size() - iPos ); + iPos = -1; + } + _DBG_FILE("CNSmlAgendaDataStore::DoReadItemL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoWriteItemL +// Write item data as buffered. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoWriteItemL( const TDesC8& aData ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoWriteItemL: BEGIN"); + if ( iState == ENSmlItemCreating || iState == ENSmlItemUpdating ) + { + if ( iItemData ) + { + if ( iPos == -1 ) + { + User::Leave( KErrEof ); + } + iItemData->InsertL( iPos, aData ); + iPos += aData.Size(); + return; + } + } + User::Leave( KErrNotReady ); + _DBG_FILE("CNSmlAgendaDataStore::DoWriteItemL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoCommitItemL +// Commit item data to database when adding or replacing item. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoCommitItemL( TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitItemL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + + if ( iState != ENSmlItemCreating && iState != ENSmlItemUpdating ) + { + User::RequestComplete( iCallerStatus, KErrNotReady ); + _DBG_FILE("CNSmlAgendaDataStore::DoCommitItemL - KErrNotReady: END"); + return; + } + + iItemData->Compress(); + TInt error( KErrNone ); + + if ( iState == ENSmlItemCreating ) + { + TRAP( error, DoCommitCreateItemL() ); + } + else // ENSmlItemUpdating + { + TRAP( error, DoCommitReplaceItemL() ); + } + iReplaceItemId = -1; + iPos = -1; + iState = ENSmlOpenAndWaiting; + iRXEntryType = iTXEntryType; + User::RequestComplete( iCallerStatus, error ); + _DBG_FILE("CNSmlAgendaDataStore::DoCommitItemL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoCloseItem +// Return to previous state and clean item buffer. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoCloseItem() + { + _DBG_FILE("CNSmlAgendaDataStore::DoCloseItem: BEGIN"); + if ( iState == ENSmlItemOpen ) + { + iPos = -1; + iState = ENSmlOpenAndWaiting; + } + _DBG_FILE("CNSmlAgendaDataStore::DoCloseItem: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoMoveItemL +// Not supported. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoMoveItemL( TSmlDbItemUid /*aUid*/, + TSmlDbItemUid /*aNewParent*/, TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoMoveItemL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + if ( iState != ENSmlOpenAndWaiting ) + { + User::RequestComplete( iCallerStatus, KErrNotReady ); + return; + } + User::RequestComplete( iCallerStatus, KErrNotSupported ); + _DBG_FILE("CNSmlAgendaDataStore::DoMoveItemL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoDeleteItemL +// Delete item from database. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoDeleteItemL( TSmlDbItemUid aUid, + TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoDeleteItemL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + if ( iState != ENSmlOpenAndWaiting ) + { + User::RequestComplete( iCallerStatus, KErrNotReady ); + return; + } + + CCalEntry* entry = NULL; + TInt err( KErrNone ); + TRAP( err, entry = iEntryView->FetchL( aUid ) ); + CleanupStack::PushL( entry ); + + if ( !entry || err == KErrNotFound ) + { + CleanupStack::PopAndDestroy( entry ); // entry + User::RequestComplete( iCallerStatus, KErrNotFound ); + return; + } + else if ( err ) + { + CleanupStack::PopAndDestroy( entry ); // entry + User::RequestComplete( iCallerStatus, err ); + return; + } + + iEntryView->DeleteL( *entry ); + CleanupStack::PopAndDestroy( entry ); // entry + + if ( iChangeFinder ) + { + TNSmlSnapshotItem item( aUid ); + iChangeFinder->ItemDeleted( item ); + } + + User::RequestComplete( iCallerStatus, KErrNone ); + _DBG_FILE("CNSmlAgendaDataStore::DoDeleteItemL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoSoftDeleteItemL +// Delete item from database. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoSoftDeleteItemL( TSmlDbItemUid /*aUid*/, + TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoSoftDeleteItemL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + User::RequestComplete( iCallerStatus, KErrNotSupported ); + _DBG_FILE("CNSmlAgendaDataStore::DoSoftDeleteItemL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoDeleteAllItemsL +// Delete all items from database. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoDeleteAllItemsL( TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoDeleteAllItemsL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + if ( iState != ENSmlOpenAndWaiting ) + { + User::RequestComplete( iCallerStatus, KErrNotReady ); + return; + } + + // Delete all items + // First searh every UIDs ... + TInt aNumSuccessfulDeleted( 0 ); + RArray uidArray; + CleanupClosePushL( uidArray ); + TCalTime zeroTime; + zeroTime.SetTimeUtcL( Time::NullTTime() ); + iEntryView->GetIdsModifiedSinceDateL( zeroTime, uidArray ); + + + // ... and then delete them + iEntryView->DeleteL( uidArray, aNumSuccessfulDeleted ); + CleanupStack::PopAndDestroy( &uidArray ); // uidArray + + // Update changefinder + if ( iChangeFinder ) + { + iChangeFinder->ResetL(); + } + iSnapshotRegistered = EFalse; + RegisterSnapshotL(); + + User::RequestComplete( iCallerStatus, KErrNone ); + + _DBG_FILE("CNSmlAgendaDataStore::DoDeleteAllItemsL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoHasSyncHistory +// Return ETrue if syncronization history is available. +// ----------------------------------------------------------------------------- +// +TBool CNSmlAgendaDataStore::DoHasSyncHistory() const + { + _DBG_FILE("CNSmlAgendaDataStore::DoHasSyncHistory: BEGIN"); + TBool ret = EFalse; + if ( iHasHistory ) + { + if ( iOpenedStoreId != iChangeFinder->DataStoreUid() ) + { + iChangeFinder->SetDataStoreUid( iOpenedStoreId ); + } + else + { + ret = ETrue; + } + } + else + { + iChangeFinder->SetDataStoreUid( iOpenedStoreId ); + } + _DBG_FILE("CNSmlAgendaDataStore::DoHasSyncHistory: END"); + return ret; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoAddedItems +// Give uid list of added items since last syncronization. +// ----------------------------------------------------------------------------- +// +const MSmlDataItemUidSet& CNSmlAgendaDataStore::DoAddedItems() const + { + _DBG_FILE("CNSmlAgendaDataStore::DoAddedItems: BEGIN"); + if ( iState == ENSmlOpenAndWaiting ) + { + iNewUids->Reset(); + TRAP_IGNORE( iChangeFinder->FindNewItemsL( *iNewUids ) ); + } + _DBG_FILE("CNSmlAgendaDataStore::DoAddedItems: END"); + return *iNewUids; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoDeletedItems +// Give uid list of deleted items since last syncronization. +// ----------------------------------------------------------------------------- +// +const MSmlDataItemUidSet& CNSmlAgendaDataStore::DoDeletedItems() const + { + _DBG_FILE("CNSmlAgendaDataStore::DoDeletedItems: BEGIN"); + if ( iState == ENSmlOpenAndWaiting ) + { + iDeletedUids->Reset(); + TRAP_IGNORE( iChangeFinder->FindDeletedItemsL( *iDeletedUids ) ); + } + _DBG_FILE("CNSmlAgendaDataStore::DoDeletedItems: END"); + return *iDeletedUids; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoSoftDeletedItems +// Give uid list of deleted items since last syncronization. +// ----------------------------------------------------------------------------- +// +const MSmlDataItemUidSet& CNSmlAgendaDataStore::DoSoftDeletedItems() const + { + _DBG_FILE("CNSmlAgendaDataStore::DoSoftDeletedItems: BEGIN"); + if ( iState == ENSmlOpenAndWaiting ) + { + iSoftDeletedUids->Reset(); + TRAP_IGNORE( + iChangeFinder->FindSoftDeletedItemsL( *iSoftDeletedUids ) ); + } + _DBG_FILE("CNSmlAgendaDataStore::DoSoftDeletedItems: END"); + return *iSoftDeletedUids; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoModifiedItems +// Give uid list of modified items since last syncronization. +// ----------------------------------------------------------------------------- +// +const MSmlDataItemUidSet& CNSmlAgendaDataStore::DoModifiedItems() const + { + _DBG_FILE("CNSmlAgendaDataStore::DoModifiedItems: BEGIN"); + if ( iState == ENSmlOpenAndWaiting ) + { + iReplacedUids->Reset(); + TRAP_IGNORE( iChangeFinder->FindChangedItemsL( *iReplacedUids ) ); + } + _DBG_FILE("CNSmlAgendaDataStore::DoModifiedItems: END"); + return *iReplacedUids; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoMovedItems +// Give uid list of moved items since last syncronization. +// ----------------------------------------------------------------------------- +// +const MSmlDataItemUidSet& CNSmlAgendaDataStore::DoMovedItems() const + { + _DBG_FILE("CNSmlAgendaDataStore::DoMovedItems: BEGIN"); + if ( iState == ENSmlOpenAndWaiting ) + { + iMovedUids->Reset(); + TRAP_IGNORE( iChangeFinder->FindMovedItemsL( *iMovedUids ) ); + } + _DBG_FILE("CNSmlAgendaDataStore::DoMovedItems: END"); + return *iMovedUids; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoResetChangeInfoL +// Reset change info that exist since last syncronization. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoResetChangeInfoL( TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoResetChangeInfoL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + if ( iState != ENSmlOpenAndWaiting ) + { + User::RequestComplete( iCallerStatus, KErrNotReady ); + return; + } + iChangeFinder->ResetL(); + iSnapshotRegistered = EFalse; + if( !iSnapshotRegistered ) + { + RegisterSnapshotL(); + } + User::RequestComplete( iCallerStatus, KErrNone ); + _DBG_FILE("CNSmlAgendaDataStore::DoResetChangeInfoL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoCommitChangeInfoL +// Commit change info that exist since last syncronization for given uid list. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoCommitChangeInfoL( TRequestStatus& aStatus, + const MSmlDataItemUidSet& aItems ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitChangeInfoL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + if ( iState != ENSmlOpenAndWaiting ) + { + User::RequestComplete( iCallerStatus, KErrNotReady ); + return; + } + iChangeFinder->CommitChangesL( aItems ); + User::RequestComplete( iCallerStatus, KErrNone ); + _DBG_FILE("CNSmlAgendaDataStore::DoCommitChangeInfoL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoCommitChangeInfoL +// Commit change info that exist since last syncronization. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoCommitChangeInfoL( TRequestStatus& aStatus ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitChangeInfoL: BEGIN"); + iCallerStatus = &aStatus; + *iCallerStatus = KRequestPending; + if ( iState != ENSmlOpenAndWaiting ) + { + User::RequestComplete( iCallerStatus, KErrNotReady ); + return; + } + iChangeFinder->CommitChangesL(); + User::RequestComplete( iCallerStatus, KErrNone ); + _DBG_FILE("CNSmlAgendaDataStore::DoCommitChangeInfoL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::RegisterSnapshotL +// Register snapshot. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::RegisterSnapshotL() + { + _DBG_FILE("CNSmlAgendaAdapter::RegisterSnapshotL(): begin"); + CArrayFixSeg* snapshot = + new ( ELeave ) CArrayFixSeg( 64 ); + CleanupStack::PushL( snapshot ); + + // First find all entries ... + RArray uidArray; + CleanupClosePushL( uidArray ); + TCalTime zeroTime; + zeroTime.SetTimeUtcL( Time::NullTTime() ); + iEntryView->GetIdsModifiedSinceDateL( zeroTime, uidArray ); + + // ... and then create snapshot items + for ( TInt i = 0; i < uidArray.Count(); i++ ) + { + TNSmlSnapshotItem newItem = CreateSnapshotItemL( uidArray[i] ); + if ( newItem.ItemId() != 0 ) + { + snapshot->InsertIsqL( newItem, iKey ); + } + } + + CleanupStack::PopAndDestroy( &uidArray ); + + iChangeFinder->SetNewSnapshot( snapshot ); + + // iChangeFinder takes ownership of items + CleanupStack::Pop( snapshot ); + iSnapshotRegistered = ETrue; + + _DBG_FILE("CNSmlAgendaAdapter::RegisterSnapshotL(): end"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::CreateSnapshotItemL +// Creates new snapshot. Method gets data from database. +// ----------------------------------------------------------------------------- +TNSmlSnapshotItem CNSmlAgendaDataStore::CreateSnapshotItemL( + const TCalLocalUid& aUid ) + { + TNSmlSnapshotItem item( 0 ); + CCalEntry* entry = iEntryView->FetchL( aUid ); + CleanupStack::PushL( entry ); + + if( entry ) + { + CCalEntry::TReplicationStatus replicationStatus = + entry->ReplicationStatusL(); + if ( CanBeSynchronized( replicationStatus ) ) + { + TUint intUid = entry->LocalUidL(); + item.SetItemId( intUid ); + item.SetLastChangedDate( + entry->LastModifiedDateL().TimeUtcL() ); + item.SetSoftDelete( EFalse ); + } + } + + CleanupStack::PopAndDestroy( entry ); // entry + return item; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoListAgendaFilesL +// List possible calendar database file names. +// ----------------------------------------------------------------------------- +// +CDesCArray* CNSmlAgendaDataStore::DoListAgendaFilesLC() const + { + CDesCArray* array = iVCalSession->ListCalFilesL(); + CleanupStack::PushL( array ); + return array; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoGetDefaultFileNameL +// Return default calendar database name. +// ----------------------------------------------------------------------------- +// +const TDesC& CNSmlAgendaDataStore::DoGetDefaultFileNameL() const + { + if ( !iDefaultStoreName ) + { + User::Leave( KErrGeneral ); + } + return *iDefaultStoreName; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::CanBeSynchronized +// Return ETrue if entry can be synchronized. +// ----------------------------------------------------------------------------- +// +TBool CNSmlAgendaDataStore::CanBeSynchronized( + const CCalEntry::TReplicationStatus& + aReplicationStatus ) const + { + return ( aReplicationStatus != CCalEntry::ERestricted ); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoOwnStoreFormatL +// Returns adapters supported store format which is read from Calendar Plug +// In Adapter own resource file. +// ----------------------------------------------------------------------------- +// +CSmlDataStoreFormat* CNSmlAgendaDataStore::DoOwnStoreFormatL() + { + _DBG_FILE("CNSmlAgendaDataStore:::DoOwnStoreFormatL(): BEGIN"); + TFileName fileName; + TParse parse; + + // Check correct Data Sync protocol + TInt value( EDataSyncNotRunning ); + TInt error = RProperty::Get( KPSUidDataSynchronizationInternalKeys, + KDataSyncStatus, + value ); + if ( error == KErrNone && + value == EDataSyncRunning ) + { + parse.Set( KNSmlDSAgendaDataStoreRsc_1_1_2, + &KDC_RESOURCE_FILES_DIR, NULL ); + } + else // error or protocol version 1.2 + { + parse.Set( KNSmlDSAgendaDataStoreRsc_1_2, + &KDC_RESOURCE_FILES_DIR, NULL ); + } + + fileName = parse.FullName(); + RResourceFile resourceFile; + BaflUtils::NearestLanguageFile( iRfs, fileName ); + + TRAPD( leavecode, resourceFile.OpenL( iRfs,fileName ) ); + if ( leavecode != 0 ) + { + CleanupStack::PopAndDestroy(); // parse + _DBG_FILE("CNSmlAgendaDataProvider::DoStoreFormatL(): Resource.OpenL has problem"); + User::Leave( leavecode ); + } + CleanupClosePushL( resourceFile ); + HBufC8* profileRes = resourceFile.AllocReadLC( NSML_AGENDA_DATA_STORE ); + TResourceReader reader; + reader.SetBuffer( profileRes ); + + CSmlDataStoreFormat* dsFormat = CSmlDataStoreFormat::NewLC( iStringPool, + reader ); + CleanupStack::Pop(); + CleanupStack::PopAndDestroy( 2 ); // resourceFile, profileRes + _DBG_FILE("CNSmlAgendaDataStore:::DoOwnStoreFormatL(): END"); + return dsFormat; + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoCommitCreateItemL +// Commit item data to database when adding item. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoCommitCreateItemL() + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitCreateItemL: BEGIN"); + iState = ENSmlOpenAndWaiting; // iState set to closed to handle leave + CCalEntry::TReplicationStatus replicationStatus; + + RBufReadStream readStream; + readStream.Open( *iItemData ); + readStream.PushL(); + + RPointerArray rdArray; + CleanupStack::PushL( PtrArrCleanupItemRArr ( CCalEntry, &rdArray ) ); + if ( iRXEntryType == ENSmlICal ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitCreateItemL: ImportICalendarL"); + iImporter->ImportICalendarL( readStream, rdArray ); + } + else if ( iRXEntryType == ENSmlVCal ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitCreateItemL: ImportVCalendarL"); + iImporter->ImportVCalendarL( readStream, rdArray ); + } + else + { + CleanupStack::PopAndDestroy( 2 ); // rdArray, readStream + _DBG_FILE("CNSmlAgendaDataStore::DoCommitCreateItemL - \ + KErrNotSupported: END"); + User::Leave( KErrNotSupported ); + } + + // If rdArray is empty or there is multiple items then return error + // Multiple items are not supported + if ( rdArray.Count() != 1 ) + { + CleanupStack::PopAndDestroy( 2 ); // rdArray, readStream + _DBG_FILE("CNSmlAgendaDataStore::DoCommitCreateItemL - \ + Multiple items are not supported: END"); + User::Leave( KErrNotSupported ); + } + + TInt err( KErrNone ); + + _DBG_FILE("CNSmlAgendaDataStore::DoCommitCreateItemL: before StoreL"); + TRAP( err, iInterimUtils->StoreL( *iEntryView, *rdArray[0], ETrue ) ); + DBG_ARGS(_S("CNSmlAgendaDataStore::DoCommitCreateItemL: after StoreL '%d'"), err ); + if ( err ) + { + CleanupStack::PopAndDestroy( 2 ); // rdArray, readStream + _DBG_FILE("CNSmlAgendaDataStore::DoCommitCreateItemL - \ + Error at storing item to database: END"); + User::Leave( KErrGeneral ); + } + + *iAddItemId = rdArray[0]->LocalUidL(); + + CCalEntry* newEntry = iEntryView->FetchL( *iAddItemId ); + + if( newEntry ) + { + CleanupStack::PushL( newEntry ); + + replicationStatus = newEntry->ReplicationStatusL(); + + if ( CanBeSynchronized( replicationStatus ) ) + { + if ( iChangeFinder ) + { + TNSmlSnapshotItem item( *iAddItemId ); + item.SetLastChangedDate( + newEntry->LastModifiedDateL().TimeUtcL() ); + item.SetSoftDelete( EFalse ); + TRAPD( changeFinderError, iChangeFinder->ItemAddedL( item ) ); + if ( changeFinderError == KErrAlreadyExists ) + { + iChangeFinder->ItemUpdatedL( item ); + } + else + { + User::LeaveIfError( changeFinderError ); + } + } + } + CleanupStack::PopAndDestroy();// newEntry, + } + CleanupStack::PopAndDestroy( 2 ); // rdArray, readStream + _DBG_FILE("CNSmlAgendaDataStore::DoCommitCreateItemL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::DoCommitReplaceItemL +// Commit item data to database when replacing item. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::DoCommitReplaceItemL() + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL: BEGIN"); + iState = ENSmlOpenAndWaiting; // iState set to closed to handle leave + CBufFlat* oldItem = CBufFlat::NewL( KNSmlItemDataExpandSize ); + CleanupStack::PushL( oldItem ); + RBufWriteStream writeStream( *oldItem ); + writeStream.PushL(); + + CCalEntry* entry = NULL; + TInt error( KErrNone ); + TRAP( error, entry = iEntryView->FetchL( iReplaceItemId ) ); + if ( error || !entry ) + { + CleanupStack::PopAndDestroy( 2 ); // writeStream, oldItem + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL - \ + Error in fetching the item: END"); + User::Leave( KErrGeneral ); + } + CleanupStack::PushL( entry ); + + // Export item from database depending on transmitted item entry type + if ( iTXEntryType == ENSmlVCal ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL: ExportVCalL"); + iExporter->ExportVCalL( *entry, writeStream ); + } +#ifdef __NSML_USE_ICAL_FEATURE + else if ( iTXEntryType == ENSmlICal ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL: ExportICalL"); + iExporter->ExportICalL( *entry, writeStream ); + } +#endif // __NSML_USE_ICAL_FEATURE + else + { + CleanupStack::PopAndDestroy( 2 ); // entry, writeStream + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL - \ + KErrNotSupported: END"); + User::Leave( KErrNotSupported ); + } + + writeStream.CommitL(); + oldItem->Compress(); + + CleanupStack::PopAndDestroy( 2 ); // entry, writeStream + + // Get original UID, geoId and Recurrence-ID properties + HBufC8* uid = NULL; + HBufC8* recurrenceId = NULL; + HBufC8* xRecurrenceId = NULL; + HBufC8* geoId = NULL; + GetPropertiesFromDataL( oldItem, uid, KVersitTokenUID() ); + GetPropertiesFromDataL( oldItem, recurrenceId, KNSmlVersitTokenRecurrenceID() ); + GetPropertiesFromDataL( oldItem, xRecurrenceId, KNSmlVersitTokenXRecurrenceID() ); + GetPropertiesFromDataL( oldItem, geoId, KNSmlVersitTokenGeoID() ); + CleanupStack::PushL( uid ); + CleanupStack::PushL( recurrenceId ); + CleanupStack::PushL( xRecurrenceId ); + CleanupStack::PushL( geoId ); + +#ifdef __NSML_MORE_DEBUG_FOR_ITEMS__ + + DBG_DUMP( ( void* )oldItem->Ptr( 0 ).Ptr(), oldItem->Size(), + _S8( "Old item from database:" ) ); + +#endif // __NSML_MORE_DEBUG_FOR_ITEMS__ + + if ( iDataMod->NeedsMerge() ) + { + // Merge data + iDataMod->MergeRxL( *iItemData, *oldItem ); + } + + // Add original UID and Recurrence-ID to merged data + // This first removes UID and Recurrence-ID from merged data + // and then adds original ones + if ( uid ) + { + SetPropertiesToDataL( uid, KVersitTokenUID() ); + } + else + { + User::Leave( KErrNotSupported ); + } + if ( recurrenceId ) + { + SetPropertiesToDataL( recurrenceId, KNSmlVersitTokenRecurrenceID() ); + } + if ( xRecurrenceId ) + { + SetPropertiesToDataL( xRecurrenceId, KNSmlVersitTokenXRecurrenceID() ); + } + if ( geoId ) + { + SetPropertiesToDataL( geoId, KNSmlVersitTokenGeoID() ); + } + +#ifdef __NSML_MORE_DEBUG_FOR_ITEMS__ + + DBG_DUMP( ( void* )iItemData->Ptr( 0 ).Ptr(), iItemData->Size(), + _S8( "New item to database:" ) ); + +#endif // __NSML_MORE_DEBUG_FOR_ITEMS__ + + CleanupStack::PopAndDestroy( 5 ); // xRecurrenceId, recurrenceId, + // uid, oldItem, geoId + + // Replace item to database + RBufReadStream readStream; + readStream.Open( *iItemData ); + readStream.PushL(); + + RPointerArray rdArray; + CleanupStack::PushL( PtrArrCleanupItemRArr ( CCalEntry, &rdArray ) ); + + // Import item to database depending on received item entry type + if ( iRXEntryType == ENSmlVCal ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL: ImportVCalendarL"); + iImporter->ImportVCalendarL( readStream, rdArray ); + } +#ifdef __NSML_USE_ICAL_FEATURE + else if ( iRXEntryType == ENSmlICal ) + { + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL: ImportICalendarL"); + iImporter->ImportICalendarL( readStream, rdArray ); + } +#endif // __NSML_USE_ICAL_FEATURE + else + { + CleanupStack::PopAndDestroy( 2 ); // rdArray, readStream + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL - \ + KErrNotSupported: END"); + User::Leave( KErrNotSupported ); + } + + // If rdArray is empty or there is multiple items then return error + // Multiple items are not supported + if ( rdArray.Count() != 1 ) + { + CleanupStack::PopAndDestroy( 2 ); // rdArray, readStream + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL - \ + Multiple items are not supported: END"); + User::Leave( KErrNotSupported ); + } + + TInt err( KErrNone ); + + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL: before StoreL"); + TRAP( err, iInterimUtils->StoreL( *iEntryView, *rdArray[0], ETrue ) ); + DBG_ARGS(_S("CNSmlAgendaDataStore::DoCommitCreateItemL: after StoreL '%d'"), err ); + if ( err ) + { + CleanupStack::PopAndDestroy( 2 ); // rdArray, readStream + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL - \ + Error at storing item to database: END"); + User::Leave( KErrGeneral ); + } + + CCalEntry::TReplicationStatus replicationStatus; + + CCalEntry* replacedEntry = iEntryView->FetchL( iReplaceItemId ); + if( replacedEntry ) + { + CleanupStack::PushL( replacedEntry ); + + replicationStatus = replacedEntry->ReplicationStatusL(); + + if ( CanBeSynchronized( replicationStatus ) ) + { + if ( iChangeFinder ) + { + TNSmlSnapshotItem item( iReplaceItemId ); + item.SetLastChangedDate( + replacedEntry->LastModifiedDateL().TimeUtcL()); + item.SetSoftDelete( EFalse ); + iChangeFinder->ItemUpdatedL( item ); + } + } + CleanupStack::PopAndDestroy(); // replacedEntry + } + + CleanupStack::PopAndDestroy( 2 ); // rdArray, readStream + + _DBG_FILE("CNSmlAgendaDataStore::DoCommitReplaceItemL: END"); + } + +// ----------------------------------------------------------------------------- +// CNSmlAgendaDataStore::GetPropertiesFromDataL +// Gets property from old item. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::GetPropertiesFromDataL( CBufFlat* aOldItem, + HBufC8*& aValue, + const TDesC8& aProperty ) + { + _DBG_FILE("CNSmlAgendaDataStore::GetPropertiesFromDataL(): begin"); + + // Gemerate property that is searched (Linebreak + property + tokencolon) + HBufC8* startBuffer = HBufC8::NewLC( KVersitTokenCRLF().Size() + + aProperty.Length() ); + TPtr8 startBufferPtr( startBuffer->Des() ); + startBufferPtr.Append( KVersitTokenCRLF() ); + startBufferPtr.Append( aProperty ); + + // Get start position of property value + TInt startPos = aOldItem->Ptr( 0 ).Find( startBufferPtr ); + + TInt endPos( KErrNotFound ); + if ( startPos != KErrNotFound ) + { + // startPos is before UID word + startPos = startPos + KVersitTokenCRLF().Length(); + + // End end position of property value + endPos = startPos + + aOldItem->Ptr( startPos ).Find( KVersitTokenCRLF() ); + + TPtrC8 tempPtr( aOldItem->Ptr( 0 ).Mid( endPos ) ); + + // If next char after linebreak is ' ' or '=' then it is only + // linebreak inside of value. This does not work with base64 coding! + while ( tempPtr[KVersitTokenCRLF().Length()] == ' ' || + tempPtr[KVersitTokenCRLF().Length()] == '=' ) + { + endPos = endPos + KVersitTokenCRLF().Length(); + TInt tempPos = aOldItem->Ptr( endPos ).Find( KVersitTokenCRLF() ); + endPos = endPos + tempPos; + tempPtr.Set( aOldItem->Ptr( 0 ).Mid( endPos ) ); + } + + // Then cut value to value parameter + delete aValue; + aValue = NULL; + TInt length = endPos - startPos; + aValue = HBufC8::NewLC( length ); + TPtr8 valuePtr( aValue->Des() ); + aOldItem->Read( startPos, valuePtr, length ); + CleanupStack::Pop( aValue ); // aValue + } + CleanupStack::PopAndDestroy( startBuffer ); // startBuffer + + _DBG_FILE("CNSmlAgendaDataStore::GetPropertiesFromDataL(): end"); + } + +// ----------------------------------------------------------------------------- +// Adds property and it's value to new item. +// This method also removes original property and it's value. +// ----------------------------------------------------------------------------- +// +void CNSmlAgendaDataStore::SetPropertiesToDataL( HBufC8*& aValue, + const TDesC8& aProperty ) + { + _DBG_FILE("CNSmlAgendaDataStore::SetPropertiesToDataL(): begin"); + + // Gemerate property that is searched (Linebreak + property + tokencolon) + HBufC8* startBuffer = HBufC8::NewLC( KVersitTokenCRLF().Size() + + aProperty.Length() ); + TPtr8 startBufferPtr( startBuffer->Des() ); + startBufferPtr.Append( KVersitTokenCRLF() ); + startBufferPtr.Append( aProperty ); + + // Get start position of property value + TInt startPos = iItemData->Ptr( 0 ).Find( startBufferPtr ); + + TInt endPos( KErrNotFound ); + if ( startPos != KErrNotFound ) + { + // startPos is before UID word + startPos = startPos + KVersitTokenCRLF().Length(); + + // End end position of property value + endPos = startPos + + iItemData->Ptr( startPos ).Find( KVersitTokenCRLF() ); + + TPtrC8 tempPtr( iItemData->Ptr( 0 ).Mid( endPos ) ); + + // If next char after linebreak is ' ' or '=' then it is only + // linebreak inside of value. This does not work with base64 coding! + while ( tempPtr[KVersitTokenCRLF().Length()] == ' ' || + tempPtr[KVersitTokenCRLF().Length()] == '=' ) + { + endPos = endPos + KVersitTokenCRLF().Length(); + TInt tempPos = iItemData->Ptr( endPos ).Find( KVersitTokenCRLF() ); + endPos = endPos + tempPos; + tempPtr.Set( iItemData->Ptr( 0 ).Mid( endPos ) ); + } + + // Delete original property and value + iItemData->Delete( startPos, endPos - startPos ); + + } + + // Add property and new value from parameter. + // First find end of VEVENT or VTODO + + // Generate VEVENT END property + HBufC8* endVEvent = HBufC8::NewLC( KVersitTokenCRLF().Size() + + KVersitTokenEND().Length() + + KVersitTokenColon().Length() + + KVersitVarTokenVEVENT().Length() ); + TPtr8 endVEventPtr( endVEvent->Des() ); + endVEventPtr.Append( KVersitTokenCRLF() ); + endVEventPtr.Append( KVersitTokenEND() ); + endVEventPtr.Append( KVersitTokenColon() ); + endVEventPtr.Append( KVersitVarTokenVEVENT() ); + + // Generate VTODO END property + HBufC8* endVTodo = HBufC8::NewLC( KVersitTokenCRLF().Size() + + KVersitTokenEND().Length() + + KVersitTokenColon().Length() + + KVersitVarTokenVTODO().Length() ); + TPtr8 endVTodoPtr( endVTodo->Des() ); + endVTodoPtr.Append( KVersitTokenCRLF() ); + endVTodoPtr.Append( KVersitTokenEND() ); + endVTodoPtr.Append( KVersitTokenColon() ); + endVTodoPtr.Append( KVersitVarTokenVTODO() ); + + // Find end of VEVENT or VTODO + endPos = iItemData->Ptr( 0 ).Find( endVEventPtr ); + if ( endPos == KErrNotFound ) + { + endPos = iItemData->Ptr( 0 ).Find( endVTodoPtr ); + if ( endPos == KErrNotFound ) + { + User::Leave( KErrNotFound ); + } + } + + // Add property and value from parameter + iItemData->InsertL( endPos, KVersitTokenCRLF() ); + iItemData->InsertL( endPos + KVersitTokenCRLF().Size(), + aValue->Des() ); + iItemData->Compress(); + + CleanupStack::PopAndDestroy( 3 ); // endVTodo, endVEvent, startBuffer + + _DBG_FILE("CNSmlAgendaDataStore::SetPropertiesToDataL(): end"); + } + +// End of File