omads/omadsextensions/adapters/sms/src/smsdatastore.cpp
changeset 36 9ba7f05d28a5
child 42 1eb2293b4d77
equal deleted inserted replaced
35:0ca79e3612d9 36:9ba7f05d28a5
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Part of SyncML Data Synchronization Plug In Adapter
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32base.h>
       
    20 #include <msvstd.h>
       
    21 #include <msvapi.h>
       
    22 #include <msvids.h>
       
    23 #include <mtclreg.h>
       
    24 #include <centralrepository.h>
       
    25 #include "smsdatastore.h"
       
    26 #include "smsdataproviderdefs.h"
       
    27 #include "logger.h"
       
    28 #include "smsadaptermsvapi.h"
       
    29 #include "vmessageparser.h"
       
    30 #include "omadsfolderobject.h"
       
    31 
       
    32 // This is used, when databuffer is not initialized
       
    33 const TInt KDataBufferNotReady = -1;
       
    34 // Size for internal CBufFlat, used to buffer SMS messages
       
    35 const TInt KDataBufferSize = 1024;
       
    36 
       
    37 _LIT8(KSmsMimeType, "text/x-vMessage");
       
    38 _LIT8(KSmsMimeVersion, "1.2");
       
    39 _LIT8(KFolderMimeType, "application/vnd.omads-folder+xml");
       
    40 _LIT8(KFolderMimeVersion, "1.2");
       
    41 
       
    42 
       
    43 // -----------------------------------------------------------------------------
       
    44 // CSmsDataStore::CSmsDataStore
       
    45 // C++ default constructor can NOT contain any code, that might leave.
       
    46 // -----------------------------------------------------------------------------
       
    47 CSmsDataStore::CSmsDataStore():
       
    48     iHasHistory(EFalse),
       
    49     iDataBaseOpened(EFalse),
       
    50     iKey(TKeyArrayFix(_FOFF(TSnapshotItem, ItemId()), ECmpTInt))
       
    51     { 
       
    52     }
       
    53   
       
    54 // -----------------------------------------------------------------------------
       
    55 // CSmsDataStore::ConstructL
       
    56 // Symbian 2nd phase constructor, can leave.
       
    57 // -----------------------------------------------------------------------------
       
    58 void CSmsDataStore::ConstructL()
       
    59     {
       
    60 	LOGGER_ENTERFN("CSmsDataStore::ConstructL");
       
    61     
       
    62     iMsvApi = CSmsAdapterMsvApi::NewL();
       
    63     
       
    64 	// Item UID sets, used to transfer change info
       
    65     iNewItems = new (ELeave) CNSmlDataItemUidSet;
       
    66     iDeletedItems = new (ELeave) CNSmlDataItemUidSet;
       
    67     iUpdatedItems = new (ELeave) CNSmlDataItemUidSet;
       
    68     iMovedItems = new (ELeave) CNSmlDataItemUidSet;
       
    69     iSoftDeletedItems = new (ELeave) CNSmlDataItemUidSet;
       
    70 	
       
    71 	iMessageParser = CVMessageParser::NewL();
       
    72 	iFolderObjectParser = COMADSFolderObject::NewL();
       
    73 	
       
    74 	LOGGER_LEAVEFN("CSmsDataStore::ConstructL");
       
    75     }
       
    76 
       
    77 // -----------------------------------------------------------------------------
       
    78 // CSmsDataStore::NewLC
       
    79 // Two-phased constructor.
       
    80 // -----------------------------------------------------------------------------
       
    81 CSmsDataStore* CSmsDataStore::NewLC()
       
    82     {
       
    83     CSmsDataStore* self = new (ELeave) CSmsDataStore;
       
    84     
       
    85 	CleanupStack::PushL(self);
       
    86   	self->ConstructL();
       
    87 
       
    88     return self;    
       
    89     }
       
    90 
       
    91     
       
    92 // -----------------------------------------------------------------------------
       
    93 // CSmsDataStore::~CSmsDataStore
       
    94 // Destructor
       
    95 // -----------------------------------------------------------------------------
       
    96 CSmsDataStore::~CSmsDataStore()
       
    97     {
       
    98     LOGGER_ENTERFN("CSmsDataStore::~CSmsDataStore()");
       
    99     
       
   100     SAFEDELETE(iFolderObjectParser);
       
   101     SAFEDELETE(iMessageParser);
       
   102     
       
   103     SAFEDELETE(iMsvApi);
       
   104 	SAFEDELETE(iChangeFinder); 	
       
   105  
       
   106 	// UID sets
       
   107 	SAFEDELETE(iNewItems);
       
   108 	SAFEDELETE(iDeletedItems);
       
   109 	SAFEDELETE(iSoftDeletedItems);
       
   110 	SAFEDELETE(iUpdatedItems);
       
   111 	SAFEDELETE(iMovedItems);
       
   112 	
       
   113 	SAFEDELETE(iDataBuffer);
       
   114 	
       
   115 	LOGGER_LEAVEFN("CSmsDataStore::~CSmsDataStore()");
       
   116     }
       
   117 
       
   118 // -----------------------------------------------------------------------------
       
   119 // CSmsDataStore::DoOpenL
       
   120 // Opens database. This operation is performed SYNCHRONOUSLY
       
   121 // -----------------------------------------------------------------------------
       
   122 void CSmsDataStore::DoOpenL(const TDesC& /*aStoreName*/, MSmlSyncRelationship& aContext, 
       
   123     TRequestStatus& aStatus)
       
   124     {
       
   125 	LOGGER_ENTERFN("CSmsDataStore::DoOpenL");
       
   126 	
       
   127 	iCallerStatus = &aStatus;
       
   128 	*iCallerStatus = KRequestPending;
       
   129 	
       
   130 	if (iDataBaseOpened)
       
   131 		{
       
   132 		User::RequestComplete(iCallerStatus, KErrInUse);
       
   133 		LOGGER_WRITE("CSmsDataStore::DoOpenL failed with KErrInUse.");
       
   134 		return;
       
   135 		}
       
   136 	
       
   137     *iContext = aContext;
       
   138 
       
   139 	// Create ChangeFinder object
       
   140     iChangeFinder = CChangeFinder::NewL(aContext, iKey, iHasHistory, KSmsDataProviderImplUid);
       
   141     
       
   142     RegisterSnapshotL();
       
   143   
       
   144     iDataBaseOpened = ETrue;
       
   145     iCurrentState = ESmsOpenAndWaiting;
       
   146 	User::RequestComplete(iCallerStatus, KErrNone);	
       
   147 	
       
   148 	LOGGER_LEAVEFN("CSmsDataStore::DoOpenL");
       
   149 	}
       
   150 
       
   151 // -----------------------------------------------------------------------------
       
   152 // CSmsDataStore::DoCancelRequest
       
   153 // Not supported, does nothing.
       
   154 // -----------------------------------------------------------------------------
       
   155 void CSmsDataStore::DoCancelRequest()
       
   156 	{
       
   157 	LOGGER_ENTERFN("CSmsDataStore::DoCancelRequestL");
       
   158 	LOGGER_LEAVEFN("CSmsDataStore::DoCancelRequestL");
       
   159 	}
       
   160 
       
   161 // -----------------------------------------------------------------------------
       
   162 // CSmsDataStore::DoStoreName
       
   163 // Returns the name of the DataStore
       
   164 // -----------------------------------------------------------------------------
       
   165 const TDesC& CSmsDataStore::DoStoreName() const
       
   166 	{
       
   167 	LOGGER_ENTERFN("CSmsDataStore::DoStoreName");
       
   168 	
       
   169 	if (iDataBaseOpened)
       
   170 		{
       
   171 		LOGGER_LEAVEFN("CSmsDataStore::DoStoreName");
       
   172 	    return KNSmlDefaultLocalDbName;
       
   173 	    }
       
   174 
       
   175 	LOGGER_LEAVEFN("CSmsDataStore::DoStoreName");
       
   176     return KNullDesC;
       
   177 	}
       
   178 
       
   179 // -----------------------------------------------------------------------------
       
   180 // CSmsDataStore::DoBeginTransactionL
       
   181 // Transactions are not supported.
       
   182 // -----------------------------------------------------------------------------
       
   183 void CSmsDataStore::DoBeginTransactionL()
       
   184  	{
       
   185  	LOGGER_ENTERFN("CSmsDataStore::DoBeginTransactionL");
       
   186  	LOGGER_WRITE("CSmsDataStore::DoBeginTransactionL leaved with KErrNotSupported.")
       
   187  	User::Leave(KErrNotSupported);
       
   188 	}
       
   189 
       
   190 // -----------------------------------------------------------------------------
       
   191 // CSmsDataStore::DoCommitTransactionL
       
   192 // Transactions are not supported.
       
   193 // -----------------------------------------------------------------------------
       
   194 void CSmsDataStore::DoCommitTransactionL(TRequestStatus& aStatus)
       
   195     {
       
   196 	LOGGER_ENTERFN("CSmsDataStore::DoCommitTransactionL"); 
       
   197 	LOGGER_WRITE("CSmsDataStore::DoCommitTransactionL failed with KErrNotSupported.");
       
   198 	
       
   199 	iCallerStatus = &aStatus;
       
   200 	User::RequestComplete(iCallerStatus, KErrNotSupported);
       
   201 	
       
   202 	LOGGER_LEAVEFN("CSmsDataStore::DoCommitTransactionL");
       
   203 	}
       
   204 
       
   205 // -----------------------------------------------------------------------------
       
   206 // CSmsDataStore::DoRevertTransaction
       
   207 // Transactions are not supported.
       
   208 // -----------------------------------------------------------------------------
       
   209 void CSmsDataStore::DoRevertTransaction(TRequestStatus& aStatus)
       
   210     {
       
   211 	LOGGER_ENTERFN("CSmsDataStore::DoRevertTransaction"); 
       
   212 	iCallerStatus = &aStatus;
       
   213 	User::RequestComplete(iCallerStatus, KErrNone);	
       
   214 	LOGGER_LEAVEFN("CSmsDataStore::DoRevertTransaction");
       
   215 	}
       
   216 
       
   217 // -----------------------------------------------------------------------------
       
   218 // CSmsDataStore::DoBeginBatchL
       
   219 // Batching is not supported.
       
   220 // -----------------------------------------------------------------------------
       
   221 void CSmsDataStore::DoBeginBatchL()
       
   222 	{
       
   223 	LOGGER_ENTERFN("CSmsDataStore::DoBeginBatchL");
       
   224 	LOGGER_WRITE("CSmsDataStore::DoBeginBatchL leaved with KErrNotSupported.");
       
   225 	User::Leave(KErrNotSupported);	
       
   226 	}
       
   227 
       
   228 // -----------------------------------------------------------------------------
       
   229 // CSmsDataStore::DoCommitBatchL
       
   230 // Batching is not supported
       
   231 // -----------------------------------------------------------------------------
       
   232 //
       
   233 void CSmsDataStore::DoCommitBatchL(RArray<TInt>& /*aResultArray*/, TRequestStatus& aStatus)
       
   234 	{
       
   235 	LOGGER_ENTERFN("CSmsDataStore::DoCommitBatchL");	
       
   236 	LOGGER_WRITE("CSmsDataStore::DoCommitBatchL failed with KErrNotSupported");
       
   237 	
       
   238 	iCallerStatus = &aStatus;
       
   239 	User::RequestComplete(iCallerStatus, KErrNotSupported);
       
   240 	
       
   241 	LOGGER_LEAVEFN("CSmsDataStore::DoCommitBatchL");
       
   242 	}
       
   243 
       
   244 // -----------------------------------------------------------------------------
       
   245 // CSmsDataStore::DoCancelBatch
       
   246 // Batching is not supported
       
   247 // -----------------------------------------------------------------------------
       
   248 void CSmsDataStore::DoCancelBatch()
       
   249 	{
       
   250 	LOGGER_ENTERFN("CSmsDataStore::DoCancelBatch");
       
   251 	LOGGER_LEAVEFN("CSmsDataStore::DoCancelBatch");
       
   252 	}
       
   253 
       
   254 // -----------------------------------------------------------------------------
       
   255 // CSmsDataStore::DoSetRemoteStoreFormatL
       
   256 // Not supported
       
   257 // -----------------------------------------------------------------------------
       
   258 //
       
   259 void CSmsDataStore::DoSetRemoteStoreFormatL(const CSmlDataStoreFormat& /*aServerDataStoreFormat*/)
       
   260 	{
       
   261 	LOGGER_ENTERFN("CSmsDataStore::DoSetRemoteStoreFormatL");
       
   262 	LOGGER_LEAVEFN("CSmsDataStore::DoSetRemoteStoreFormatL");
       
   263 	}
       
   264 
       
   265 // -----------------------------------------------------------------------------
       
   266 // CSmsDataStore::DoSetRemoteMaxObjectSize
       
   267 // Not supported
       
   268 // -----------------------------------------------------------------------------
       
   269 void CSmsDataStore::DoSetRemoteMaxObjectSize(TInt /*aServerMaxObjectSize*/)
       
   270  	{
       
   271 	LOGGER_ENTERFN("CSmsDataStore::DoSetRemoteMaxObjectSize");
       
   272 	LOGGER_LEAVEFN("CSmsDataStore::DoSetRemoteMaxObjectSize");
       
   273 	}
       
   274 
       
   275 // -----------------------------------------------------------------------------
       
   276 // CSmsDataStore::DoMaxObjectSize
       
   277 // 
       
   278 // -----------------------------------------------------------------------------
       
   279 TInt CSmsDataStore::DoMaxObjectSize() const
       
   280 	{
       
   281 	LOGGER_ENTERFN("CSmsDataStore::DoMaxObjectSize");
       
   282     LOGGER_LEAVEFN("CSmsDataStore::DoMaxObjectSize");
       
   283     return 0;
       
   284 	}
       
   285 
       
   286 // -----------------------------------------------------------------------------
       
   287 // CSmsDataStore::DoOpenItemL
       
   288 // Opens item in the DataStore, reads it (either completely or partially) 
       
   289 // to the temporary buffer where it can be later read to the remote database.
       
   290 // -----------------------------------------------------------------------------
       
   291 void CSmsDataStore::DoOpenItemL(TSmlDbItemUid aUid, TBool& aFieldChange, 
       
   292 	TInt& aSize, TSmlDbItemUid& aParent, TDes8& aMimeType, 
       
   293 	TDes8& aMimeVer, TRequestStatus& aStatus)
       
   294 	{
       
   295 	LOGGER_ENTERFN("CSmsDataStore::DoOpenItemL");
       
   296 
       
   297     LOGGER_WRITE_1("Opening item %d.", aUid);
       
   298     
       
   299 	// Store these for later use
       
   300 	iCallerStatus = &aStatus;
       
   301 	*iCallerStatus = KRequestPending;
       
   302 	
       
   303 	// Check that we're in a proper state
       
   304 	if (iCurrentState != ESmsOpenAndWaiting)
       
   305 		{
       
   306 		LOGGER_WRITE_1("CSmsDataStore::DoOpenItemL, Incorrect state: %d", iCurrentState);
       
   307 		}
       
   308     
       
   309     // Allocate new buffer
       
   310     SAFEDELETE(iDataBuffer);
       
   311     iDataBuffer = CBufFlat::NewL(KDataBufferSize);
       
   312 
       
   313     TBool userFolderFound(EFalse);
       
   314     TTime timeStamp;
       
   315     TPtrC folderName;
       
   316     userFolderFound = iMsvApi->FindUserFolderL(aUid, folderName, timeStamp);
       
   317     if (userFolderFound)
       
   318         {
       
   319         iMimeType = EMessageFolder;
       
   320         iParentId = KMsvMyFoldersEntryIdValue;
       
   321         
       
   322         iFolderObjectParser->SetName(folderName);
       
   323         iFolderObjectParser->SetCreatedDate(timeStamp.DateTime());
       
   324         iFolderObjectParser->SetModifiedDate(timeStamp.DateTime());
       
   325         iFolderObjectParser->ExportFolderXmlL(*iDataBuffer); 
       
   326         }
       
   327     else
       
   328         {
       
   329         iMimeType = ESmsMessage;        
       
   330         iMessageParser->ResetAll();
       
   331         
       
   332         TBool unread;
       
   333         TMsvId parent;
       
   334         TRAPD(error, iMsvApi->RetrieveSML(aUid, parent, *iMessageParser, unread));
       
   335         if(error != KErrNone)
       
   336 		    {
       
   337 		    User::RequestComplete(iCallerStatus, KErrNotFound); 
       
   338 		    LOGGER_WRITE_1("RetrieveSML(aUid, &parser, flags) leaved with %d.", error);
       
   339 		    return;
       
   340 		    }
       
   341 		    
       
   342         iParentId = parent;
       
   343         iMessageParser->ConstructMessageL(*iDataBuffer);
       
   344         }
       
   345     
       
   346     // Adjust buffer
       
   347     iDataBuffer->Compress();
       
   348     iReaderPosition = 0;
       
   349     iCurrentState = ESmsItemOpen;		
       
   350 
       
   351 	// Return these
       
   352 	aFieldChange = EFalse;
       
   353 	aParent = iParentId;
       
   354     aSize = iDataBuffer->Size();
       
   355     	
       
   356     if (iMimeType == EMessageFolder)
       
   357         {
       
   358         TInt targetLength = KFolderMimeType().Length();
       
   359     	if (aMimeType.MaxLength() < targetLength)
       
   360     	    targetLength = aMimeType.MaxLength();
       
   361     	aMimeType.Copy(KFolderMimeType().Ptr(), targetLength);
       
   362 
       
   363         // Set mime version (do not exceed the allocated buffer)
       
   364     	targetLength = KFolderMimeVersion().Length();
       
   365     	if (aMimeVer.MaxLength() < targetLength)
       
   366     	    targetLength = aMimeVer.MaxLength();
       
   367     	aMimeVer.Copy(KFolderMimeVersion().Ptr(), targetLength);
       
   368         }
       
   369     else // ESmsMessage
       
   370         {   
       
   371     	TInt targetLength = KSmsMimeType().Length();
       
   372     	if (aMimeType.MaxLength() < targetLength)
       
   373     	    targetLength = aMimeType.MaxLength();
       
   374     	aMimeType.Copy(KSmsMimeType().Ptr(), targetLength);
       
   375 
       
   376         // Set mime version (do not exceed the allocated buffer)
       
   377     	targetLength = KSmsMimeVersion().Length();
       
   378     	if (aMimeVer.MaxLength() < targetLength)
       
   379     	    targetLength = aMimeVer.MaxLength();
       
   380     	aMimeVer.Copy(KSmsMimeVersion().Ptr(), targetLength);
       
   381         }
       
   382 		
       
   383    	// Signal we're complete
       
   384 	User::RequestComplete(iCallerStatus, KErrNone); 
       
   385 
       
   386 	LOGGER_LEAVEFN("CSmsDataStore::DoOpenItemL");
       
   387 	}
       
   388 
       
   389 // -----------------------------------------------------------------------------
       
   390 // CSmsDataStore::DoCreateItemL
       
   391 // Create new item to the message store.
       
   392 // Return the id number of the newly created item
       
   393 // -----------------------------------------------------------------------------
       
   394 void CSmsDataStore::DoCreateItemL(TSmlDbItemUid& aUid, TInt aSize, 
       
   395     TSmlDbItemUid aParent, const TDesC8& aMimeType, const TDesC8& /*aMimeVer*/, 
       
   396     TRequestStatus& aStatus)
       
   397 	{
       
   398 	LOGGER_ENTERFN("CSmsDataStore::DoCreateItemL");
       
   399 	
       
   400 	// Store some variables for further use
       
   401 	iCallerStatus = &aStatus;
       
   402 	*iCallerStatus = KRequestPending;
       
   403 	
       
   404 	// Ensure that we're in proper state
       
   405 	if (iCurrentState != ESmsOpenAndWaiting)
       
   406 		{
       
   407 		LOGGER_WRITE_1("Incorrect state: %d", iCurrentState);
       
   408 		}	
       
   409 
       
   410 	// Check MIME type
       
   411 	LOG(aMimeType);
       
   412 	if (aMimeType.Compare( KFolderMimeType() ) == 0)	
       
   413 		{
       
   414 		iMimeType = EMessageFolder;
       
   415 		}
       
   416 	else if (aMimeType.Compare( KSmsMimeType() ) == 0)
       
   417 		{
       
   418 		iMimeType = ESmsMessage;
       
   419 		}
       
   420 	else
       
   421 		{
       
   422 		User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   423 		LOGGER_WRITE("Bad MIME type");
       
   424 		return;
       
   425 		}
       
   426 	
       
   427 	LOGGER_WRITE_1( "Parent folder: %d", aParent);
       
   428 	if ((iMimeType == EMessageFolder && aParent != KMsvMyFoldersEntryIdValue) ||
       
   429 	    (iMimeType == ESmsMessage && !iMsvApi->ValidFolderL(aParent)))
       
   430 	    {
       
   431 		User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   432 		LOGGER_WRITE( "Bad parent folder");
       
   433 		return;	    
       
   434 	    }
       
   435 
       
   436 	// Ensure that we've got enough disk space for the item
       
   437 	if(iMsvApi->DiskSpaceBelowCriticalLevelL(aSize))
       
   438 		{
       
   439 		User::RequestComplete(iCallerStatus, KErrDiskFull);
       
   440 		LOGGER_WRITE("Disk full");
       
   441 		return;
       
   442 		}	
       
   443 			
       
   444     // Store uid values
       
   445     iCreatedUid = &aUid;
       
   446 	iParentId = aParent; 
       
   447     
       
   448     // Create message buffer, item will be written into this buffer
       
   449 	SAFEDELETE(iDataBuffer);
       
   450 	iDataBuffer = CBufFlat::NewL(KDataBufferSize);
       
   451 	iWriterPosition = 0;
       
   452 	iCurrentState = ESmsItemCreating;
       
   453 	
       
   454 	// Signal we're complete
       
   455 	User::RequestComplete( iCallerStatus, KErrNone );
       
   456     
       
   457     LOGGER_LEAVEFN("CSmsDataStore::DoCreateItemL");
       
   458 	}
       
   459 
       
   460 // -----------------------------------------------------------------------------
       
   461 // CSmsDataStore::DoReplaceItemL
       
   462 // Begin the replace operation, ensure that the item really exists
       
   463 // -----------------------------------------------------------------------------
       
   464 void CSmsDataStore::DoReplaceItemL(TSmlDbItemUid aUid, TInt aSize, TSmlDbItemUid aParent, 
       
   465     TBool /*aFieldChange*/, TRequestStatus& aStatus)
       
   466 	{
       
   467 	LOGGER_ENTERFN("CSmsDataStore::DoReplaceItemL");
       
   468 	LOGGER_WRITE_1("Replacing item %d.", aUid);
       
   469 	LOGGER_WRITE_1("Parent folder: %d.", aParent);
       
   470 	
       
   471 	// Store some variables for further use
       
   472 	iCallerStatus = &aStatus;
       
   473 	*iCallerStatus = KRequestPending;
       
   474 	
       
   475 	// Ensure proper state
       
   476 	if (iCurrentState != ESmsOpenAndWaiting)
       
   477 		{
       
   478 		LOGGER_WRITE_1("Incorrect state: %d", iCurrentState);
       
   479 		}
       
   480 	 
       
   481 	// Ensure that we've got enough disk space for the item
       
   482 	if (iMsvApi->DiskSpaceBelowCriticalLevelL(aSize))
       
   483 		{
       
   484 		User::RequestComplete(iCallerStatus, KErrDiskFull);
       
   485 		LOGGER_WRITE("Disk full");
       
   486 		return;
       
   487 		}
       
   488 			 
       
   489 	// Find entry
       
   490 	CMsvEntry* entry(NULL);
       
   491 	TRAPD(error, entry = iMsvApi->MsvSessionL()->GetEntryL(aUid));
       
   492 	if (error != KErrNone)
       
   493 		{
       
   494 		User::RequestComplete(iCallerStatus, KErrNotFound);
       
   495 		LOGGER_WRITE("Item not found");
       
   496 		return;
       
   497 		}
       
   498 
       
   499 	// This is the representation of the actual message
       
   500 	TMsvEntry tEntry = entry->Entry();
       
   501 	
       
   502 	// Not needed anymore
       
   503 	SAFEDELETE(entry);	
       
   504 	
       
   505 	// Check entry type
       
   506 	if (tEntry.iType == KUidMsvFolderEntry)
       
   507 	    {
       
   508 	    iMimeType = EMessageFolder;
       
   509 	    LOGGER_WRITE("Type: folder");
       
   510 	    }
       
   511 	else
       
   512 	    {
       
   513 	    iMimeType = ESmsMessage;
       
   514 	    LOGGER_WRITE("Type: SMS message");
       
   515 	    }   
       
   516     
       
   517     if ((iMimeType == EMessageFolder && aParent != KMsvMyFoldersEntryIdValue) ||
       
   518         (iMimeType == ESmsMessage && !iMsvApi->ValidFolderL(aParent) ||
       
   519         (aParent != tEntry.Parent())))
       
   520         {
       
   521         User::RequestComplete(iCallerStatus, KErrNotSupported);
       
   522         LOGGER_WRITE_1("Bad parent folder, message entry parent is %d", tEntry.Parent());
       
   523         return;    
       
   524         }    
       
   525 	
       
   526 	// Store these for further use
       
   527 	iParentId = aParent;
       
   528 	iCurrentId = aUid;
       
   529 
       
   530 	// Create temporary buffer for message data, item will be written here
       
   531     SAFEDELETE(iDataBuffer);
       
   532     iDataBuffer = CBufFlat::NewL(KDataBufferSize);
       
   533 	iWriterPosition = 0;
       
   534 	iCurrentState = ESmsItemUpdating;
       
   535 	
       
   536 	// Signal we're complete
       
   537 	User::RequestComplete(iCallerStatus, KErrNone);
       
   538 
       
   539 	LOGGER_LEAVEFN("CSmsDataStore::DoReplaceItemL");
       
   540 	}
       
   541 
       
   542 // -----------------------------------------------------------------------------
       
   543 // CSmsDataStore::DoReadItemL
       
   544 // Read specified amount of data from the temporary buffer
       
   545 // -----------------------------------------------------------------------------
       
   546 void CSmsDataStore::DoReadItemL(TDes8& aBuffer)
       
   547 	{
       
   548 	LOGGER_ENTERFN("CSmsDataStore::DoReadItemL");
       
   549 	
       
   550 	// Check that we're in proper state
       
   551 	if (iCurrentState != ESmsItemOpen || !iDataBuffer)
       
   552 		{
       
   553 		LOGGER_WRITE("CSmsDataStore::DoReadItemL leaved with KErrNotReady.");
       
   554 		User::Leave(KErrNotReady);
       
   555 		}
       
   556 
       
   557 	if (iReaderPosition == KDataBufferNotReady)
       
   558 		{
       
   559 		LOGGER_WRITE("CSmsDataStore::DoReadItemL leaved with KErrEof.");
       
   560 		User::Leave(KErrEof);
       
   561 		}
       
   562 		
       
   563 	// This is how much we've got left in the buffer
       
   564 	TInt left = iDataBuffer->Size() - iReaderPosition;
       
   565 	
       
   566 	// Make sure that there's something to read
       
   567 	if(left > 0)
       
   568 		{
       
   569 		// This is how much there's space in the destination buffer
       
   570 		TInt destSize = aBuffer.MaxSize();
       
   571 
       
   572 		// This is how much we can read
       
   573 		TInt toRead = destSize < left ? destSize : left;
       
   574 
       
   575 		// Read the data from the buffer, then update the position
       
   576 		iDataBuffer->Read(iReaderPosition, aBuffer, toRead);
       
   577 		iReaderPosition += toRead;
       
   578 		}
       
   579 	else
       
   580 		{
       
   581 		iReaderPosition = KDataBufferNotReady;
       
   582 		LOGGER_WRITE("CSmsDataStore::DoReadItemL leaved with KErrEof.");
       
   583 		User::Leave(KErrEof);
       
   584 		}
       
   585 
       
   586 	LOGGER_LEAVEFN("CSmsDataStore::DoReadItemL");	
       
   587 	}
       
   588 
       
   589 // -----------------------------------------------------------------------------
       
   590 // CSmsDataStore::DoWriteItemL
       
   591 // Write specified amount of data to the temporary buffer
       
   592 // -----------------------------------------------------------------------------
       
   593 void CSmsDataStore::DoWriteItemL(const TDesC8& aData)
       
   594 	{
       
   595 	LOGGER_ENTERFN("CSmsDataStore::DoWriteItemL");
       
   596 
       
   597 	// Ensure that we're in proper state
       
   598     if ( iCurrentState != ESmsItemCreating && iCurrentState != ESmsItemUpdating )
       
   599     	{
       
   600     	LOGGER_WRITE("CSmsDataStore::DoWriteItemL leaved with KErrNotReady.");
       
   601     	User::Leave( KErrNotReady );
       
   602     	}
       
   603     		
       
   604 	// Calculate total size
       
   605 	TInt totalSize = aData.Size() + iDataBuffer->Size();
       
   606 	    
       
   607     // Check that we have enough disk space to store this much data
       
   608 	if ( iMsvApi->DiskSpaceBelowCriticalLevelL( totalSize ) )
       
   609 	    {
       
   610 	    LOGGER_WRITE("CSmsDataStore::DoWriteItemL leaved with KErrDiskFull.");
       
   611 	    User::Leave(KErrDiskFull);
       
   612 	    }
       
   613 	    
       
   614 	// Add data to buffer
       
   615     iDataBuffer->InsertL( iWriterPosition, aData );
       
   616     iWriterPosition += aData.Size();
       
   617 
       
   618 	LOGGER_LEAVEFN("CSmsDataStore::DoWriteItemL");	
       
   619 	}
       
   620 
       
   621 // -----------------------------------------------------------------------------
       
   622 // CSmsDataStore::DoCommitItemL
       
   623 // Commits item from temporary buffer to the message store
       
   624 // -----------------------------------------------------------------------------
       
   625 void CSmsDataStore::DoCommitItemL(TRequestStatus& aStatus)
       
   626 	{
       
   627 	LOGGER_ENTERFN("CSmsDataStore::DoCommitItemL");
       
   628 	TInt error(KErrNone);
       
   629 	
       
   630 	// Store some variables
       
   631 	iCallerStatus = &aStatus;
       
   632 	*iCallerStatus = KRequestPending;
       
   633 	
       
   634 	// Check that we're in proper state
       
   635 	if ((iCurrentState != ESmsItemCreating && iCurrentState != ESmsItemUpdating) || !iDataBuffer)
       
   636 		{
       
   637 		User::RequestComplete(iCallerStatus, KErrNotReady);
       
   638 		LOGGER_WRITE_1("Bad state: %d", iCurrentState);
       
   639 		return;
       
   640 		}
       
   641 
       
   642 	iDataBuffer->Compress();
       
   643 	TInt size = iDataBuffer->Size();
       
   644 	
       
   645 	// Variable to hold the information whether SMS message is unread or not for Change Finder.
       
   646 	// For message folders this information is not relevant and value is EFalse by default.	
       
   647 	TBool unread(EFalse);
       
   648 	
       
   649 	if ( iMimeType == ESmsMessage )
       
   650 		{
       
   651 		// Reset parser
       
   652         iMessageParser->ResetAll();
       
   653         
       
   654         // This function returns the index, where the parsing ends (>=0)
       
   655         // (the error codes are in the range below 0)
       
   656         error = iMessageParser->ParseMessageL(iDataBuffer->Ptr(0));
       
   657         
       
   658 		if ( error >= 0 )
       
   659 		    {
       
   660     		unread = iMessageParser->iStatus.Compare(KVMsgStatusUnread) == 0 ? ETrue : EFalse;
       
   661     		    		
       
   662     		// Check the datastore state. We're either creating or updating an item.
       
   663     		if (iCurrentState == ESmsItemCreating)
       
   664     			{
       
   665     			TMsvId id;
       
   666     			TMsvId temporaryParent = iParentId;
       
   667     			// in message sending case, save message first to drafts folder
       
   668     			if ( iParentId == KMsvGlobalOutBoxIndexEntryId )
       
   669     			    {
       
   670     			    temporaryParent = KMsvDraftEntryId;
       
   671     			    }
       
   672     			
       
   673     			TRAP(error, iMsvApi->AddSML(*iMessageParser, temporaryParent, id));
       
   674     			if ( error == KErrNone )
       
   675     				{
       
   676         			*iCreatedUid = id;
       
   677         			iCurrentId = id;
       
   678     				}
       
   679     			else
       
   680         			{
       
   681     				LOGGER_WRITE_1("iMsvApi->AddSML leaved with %d.", error);
       
   682     	    		}
       
   683     			}
       
   684     		else // EItemUpdating
       
   685     			{
       
   686     		    if ( iParentId == KMsvGlobalInBoxIndexEntryId )
       
   687     		    	{
       
   688     		    	// For arrived message in Inbox only status is updated
       
   689     		    	TRAP(error, iMsvApi->UpdateSMStatusL( iCurrentId, *iMessageParser));
       
   690     		    	}
       
   691     		    else
       
   692     		    	{
       
   693 	    			TRAP(error, iMsvApi->ReplaceSML(iCurrentId, *iMessageParser));
       
   694     		    	}
       
   695     			if(error != KErrNone)
       
   696     			    {
       
   697     				LOGGER_WRITE_1("iMsvApi->ReplaceSML leaved with %d.", error);
       
   698     				}
       
   699     			}
       
   700 		    }
       
   701     	else
       
   702     	    {
       
   703    		    LOGGER_WRITE_1("iMessageParser->ParseMessageL failed with %d.", error);
       
   704    		    }
       
   705 		} // if (iMimeType == ESmsMessage)
       
   706 		
       
   707 	else // EMessageFolder
       
   708 	    {
       
   709 	    error = iFolderObjectParser->ImportFolderXml(iDataBuffer->Ptr(0));
       
   710 	    
       
   711 	    if ( error == KErrNone )
       
   712 	        {
       
   713 	        const TDesC& name = iFolderObjectParser->GetName();
       
   714 	        
       
   715 	        if ( name.Length() > 0 )
       
   716 	            {
       
   717 	            if ( iCurrentState == ESmsItemCreating )
       
   718 	                {
       
   719 	                TMsvId id;
       
   720 	                error = iMsvApi->AddUserFolderL( id, name );
       
   721 	                if ( error == KErrNone )
       
   722 	                    {
       
   723 	                    *iCreatedUid = id;
       
   724 	                    iCurrentId = id;
       
   725 	                    }
       
   726 	                else
       
   727 	                    {
       
   728 	                    LOGGER_WRITE_1("iMsvApi->AddFolderL failed with %d", error);
       
   729 	                    }    
       
   730 	                }
       
   731 	            else // Updating
       
   732 	                {
       
   733 	                error = iMsvApi->UpdateUserFolderL( iCurrentId, name );
       
   734 	                if ( error != KErrNone )
       
   735 	                    {
       
   736 	                    LOGGER_WRITE_1("iMsvApi->UpdateFolderL failed with %d", error);
       
   737 	                    }
       
   738 	                }    
       
   739 	            }
       
   740 	        else
       
   741 	            {
       
   742 	            LOGGER_WRITE("No folder name available");
       
   743 	            error = KErrArgument;
       
   744 	            }    
       
   745 	        }
       
   746 	    }
       
   747 	
       
   748 	// Send the message if the parent folder is outbox
       
   749     if( iParentId == KMsvGlobalOutBoxIndexEntryId &&
       
   750         iMimeType == ESmsMessage &&
       
   751         iCurrentState == ESmsItemCreating &&
       
   752         error == KErrNone )
       
   753 		{
       
   754 		LOGGER_WRITE("CSmsDataStore::DoCommitItemL, sending message.");
       
   755 		
       
   756 		TRAP( error, iMsvApi->MoveSML( iCurrentId, iParentId ) );
       
   757 		if( error != KErrNone )
       
   758 			{
       
   759 			LOGGER_WRITE_1("Moving to folder failed with %d", error);
       
   760 			iMsvApi->DeleteSML( iCurrentId );
       
   761 			}
       
   762 		else
       
   763 			{
       
   764 			TRAP( error, iMsvApi->SendSML(iCurrentId) );
       
   765 			if ( error != KErrNone )
       
   766 				{
       
   767 				LOGGER_WRITE_1("iMsvApi->SendSML failed with %d.", error);
       
   768 				iMsvApi->DeleteSML( iCurrentId );
       
   769 				}
       
   770 			}
       
   771 		}   
       
   772     
       
   773     if ( error == KErrNone ) // Update Change Finder
       
   774         {
       
   775         CMsvSession* msvSession = iMsvApi->MsvSessionL();   
       
   776         TMsvId service;
       
   777         TMsvEntry msgEntry;
       
   778         
       
   779         // Inform ChangeFinder of added item
       
   780         TSnapshotItem snapshotItem( iCurrentId, iParentId, unread );
       
   781         error = msvSession->GetEntry( iCurrentId, service, msgEntry );
       
   782    
       
   783         if ( error == KErrNone )
       
   784             {
       
   785             snapshotItem.SetLastChangedDate( msgEntry.iDate );
       
   786             if ( iMimeType == EMessageFolder )
       
   787                 {
       
   788                 snapshotItem.SetFolderNameL( msgEntry.iDetails );
       
   789                 }
       
   790         
       
   791             if ( iCurrentState == ESmsItemCreating )
       
   792                 {
       
   793                 iChangeFinder->ItemAddedL( snapshotItem );
       
   794                 }
       
   795             else
       
   796                 {
       
   797                 iChangeFinder->ItemUpdatedL( snapshotItem );
       
   798                 }    
       
   799             }
       
   800         else
       
   801             {
       
   802             LOGGER_WRITE_1("CMsvSession::GetEntry failed with %d", error);
       
   803             }    
       
   804         }
       
   805 		
       
   806 	// Reset and destroy write buffer, it's no longer needed
       
   807 	iWriterPosition = KDataBufferNotReady;
       
   808 	SAFEDELETE(iDataBuffer);
       
   809 		
       
   810 	// We'll be waiting for next event, signal we're done
       
   811 	iCurrentState = ESmsOpenAndWaiting;
       
   812 	User::RequestComplete(iCallerStatus, error);
       
   813  
       
   814  	LOGGER_LEAVEFN("CSmsDataStore::DoCommitItemL");
       
   815 	}
       
   816 
       
   817 // -----------------------------------------------------------------------------
       
   818 // CSmsDataStore::DoCloseItem
       
   819 // Closes open item in the data store
       
   820 // -----------------------------------------------------------------------------
       
   821 void CSmsDataStore::DoCloseItem()
       
   822 	{
       
   823 	LOGGER_ENTERFN("CSmsDataStore::DoCloseItem");
       
   824 	
       
   825 	// Make sure that we're opened an item
       
   826 	if ( iCurrentState == ESmsItemOpen )
       
   827 		{
       
   828 		// Reset read buffer 
       
   829 		iReaderPosition = KDataBufferNotReady;
       
   830 		SAFEDELETE(iDataBuffer);
       
   831 		
       
   832 		// Start to wait for the next operation		
       
   833 		iCurrentState = ESmsOpenAndWaiting;
       
   834 		}
       
   835 	else 
       
   836 		{
       
   837 		LOGGER_WRITE_1("CSmsDataStore::DoCloseItem, invalid state %d.", iCurrentState);
       
   838 		}
       
   839 	
       
   840 	LOGGER_LEAVEFN("CSmsDataStore::DoCloseItem");
       
   841 	}
       
   842 
       
   843 // -----------------------------------------------------------------------------
       
   844 // CSmsDataStore::DoMoveItemL
       
   845 // Moves item from one folder to another in the message store
       
   846 // -----------------------------------------------------------------------------
       
   847 void CSmsDataStore::DoMoveItemL(TSmlDbItemUid aUid, TSmlDbItemUid aNewParent, TRequestStatus& aStatus)
       
   848 	{
       
   849 	LOGGER_ENTERFN("CSmsDataStore::DoMoveItemL");
       
   850 	
       
   851 	LOGGER_WRITE_1("Moving item %d.", aUid);
       
   852 	
       
   853 	// Store some variables for further use
       
   854 	iCallerStatus = &aStatus;
       
   855 	*iCallerStatus = KRequestPending;
       
   856 
       
   857     // Check that we're in proper state
       
   858 	if (iCurrentState != ESmsOpenAndWaiting) 
       
   859 		{
       
   860 		LOGGER_WRITE_1("CSmsDataStore::DoMoveItemL, Incorrect state: %d", iCurrentState);
       
   861 		}
       
   862 
       
   863     TInt error_move(KErrNone);
       
   864 	TRAP(error_move, iMsvApi->MoveSML(aUid, aNewParent));
       
   865 	if(error_move != KErrNone)
       
   866 		{
       
   867 		User::RequestComplete(iCallerStatus, error_move); 
       
   868 		LOGGER_WRITE_1("iMsvApi->MoveSML leaved with %d.", error_move);
       
   869 		return;
       
   870 		}
       
   871 
       
   872 	// Inform ChangeFinder of the moved item
       
   873 	TSnapshotItem snapshotItem(aUid, aNewParent);
       
   874 	iChangeFinder->ItemMovedL(snapshotItem);
       
   875 
       
   876    	// Signal we're done
       
   877     User::RequestComplete(iCallerStatus, KErrNone);
       
   878     
       
   879     LOGGER_LEAVEFN("CSmsDataStore::DoMoveItemL");
       
   880 	}
       
   881 
       
   882 // -----------------------------------------------------------------------------
       
   883 // CSmsDataStore::DoDeleteItemL
       
   884 // Removes item from the message store
       
   885 // -----------------------------------------------------------------------------
       
   886 void CSmsDataStore::DoDeleteItemL(TSmlDbItemUid aUid, TRequestStatus& aStatus)
       
   887 	{
       
   888 	LOGGER_ENTERFN("CSmsDataStore::DoDeleteItemL");
       
   889 
       
   890 	// Store some variables for further use
       
   891 	iCallerStatus = &aStatus;
       
   892 	*iCallerStatus = KRequestPending;
       
   893     
       
   894     // Check that we're in proper state
       
   895 	if (iCurrentState != ESmsOpenAndWaiting) 
       
   896 		{
       
   897 		LOGGER_WRITE_1("CSmsDataStore::DoDeleteItemL, Incorrect state: %d", iCurrentState);
       
   898 		}
       
   899 		
       
   900     TInt error(KErrNone);	
       
   901 		
       
   902 	// Check if this is a user folder
       
   903 	TBool userFolder = iMsvApi->FindUserFolderL(aUid);
       
   904 	
       
   905 	if (userFolder)
       
   906 	    {
       
   907 	    LOGGER_WRITE_1("Delete user folder %d", aUid);
       
   908 	    
       
   909 	    // First delete SMS messages under the folder
       
   910 	    CMsvEntrySelection* deletedItems = iMsvApi->CleanFolderGetMsvIdsL(aUid);
       
   911 	    CleanupStack::PushL(deletedItems);
       
   912 	    
       
   913 	    for (TInt i = 0; i < deletedItems->Count(); i++)
       
   914 	        {
       
   915 	        TMsvId id = deletedItems->At(i);
       
   916 	        TSnapshotItem item(id);
       
   917 	        iChangeFinder->ItemDeletedL(item);
       
   918 	        }
       
   919 	    CleanupStack::PopAndDestroy(deletedItems);    
       
   920 	    
       
   921 	    // Then delete the actual folder
       
   922 	    // Note: folder is not deleted if it contains other message items (like MMS)
       
   923         TRAP(error, iMsvApi->DeleteUserFolderL(aUid));
       
   924 	    }
       
   925 	else
       
   926 	    {
       
   927     	LOGGER_WRITE_1("Delete SMS message %d", aUid);
       
   928     	TRAP(error, iMsvApi->DeleteSML(aUid))
       
   929 	    }
       
   930 	    
       
   931 	if ( error != KErrNone )
       
   932 	    {
       
   933 		User::RequestComplete(iCallerStatus, error); 
       
   934 		LOGGER_WRITE_1("iMsvApi function call leaved with %d", error);
       
   935 		return;	    
       
   936 	    }
       
   937 	    
       
   938 	// Inform ChangeFinder of the removed item
       
   939 	TSnapshotItem item(aUid);
       
   940 	iChangeFinder->ItemDeletedL(item);
       
   941     	
       
   942 	// Signal we're done
       
   943 	User::RequestComplete(iCallerStatus, KErrNone);
       
   944 
       
   945 	LOGGER_LEAVEFN("CSmsDataStore::DoDeleteItemL");
       
   946 	}
       
   947 
       
   948 // -----------------------------------------------------------------------------
       
   949 // CSmsDataStore::DoSoftDeleteItemL
       
   950 // Soft delete is not supported.
       
   951 // -----------------------------------------------------------------------------
       
   952 void CSmsDataStore::DoSoftDeleteItemL(TSmlDbItemUid /*aUid*/, TRequestStatus& aStatus)
       
   953 	{
       
   954 	LOGGER_ENTERFN("CSmsDataStore::DoSoftDeleteItemL");	
       
   955 	
       
   956 	iCallerStatus = &aStatus;
       
   957 	*iCallerStatus = KRequestPending;
       
   958 	
       
   959 	User::RequestComplete(iCallerStatus, KErrNotSupported);
       
   960 	
       
   961 	LOGGER_LEAVEFN("CSmsDataStore::DoSoftDeleteItemL");
       
   962 	}
       
   963 
       
   964 // -----------------------------------------------------------------------------
       
   965 // CSmsDataStore::DoDeleteAllItemsL
       
   966 // Deletes all items in the standard folders of message store
       
   967 // -----------------------------------------------------------------------------
       
   968 void CSmsDataStore::DoDeleteAllItemsL(TRequestStatus& aStatus)
       
   969 	{
       
   970 	LOGGER_ENTERFN("CSmsDataStore::DoDeleteAllItemsL");
       
   971 	
       
   972 	// Store some variables for further use	
       
   973 	iCallerStatus = &aStatus;
       
   974 	*iCallerStatus = KRequestPending;
       
   975 	
       
   976    // Check that we're in proper state
       
   977 	if (iCurrentState != ESmsOpenAndWaiting) 
       
   978 		{
       
   979 		LOGGER_WRITE_1("CSmsDataStore::DoDeleteAllItemsL, Incorrect state: %d", iCurrentState);
       
   980 		}	
       
   981 	
       
   982 	// Delete all messages in the standard folders (except outbox)
       
   983 	iMsvApi->CleanFolderL(KMsvGlobalInBoxIndexEntryId);
       
   984 	iMsvApi->CleanFolderL(KMsvDraftEntryId);
       
   985 	iMsvApi->CleanFolderL(KMsvSentEntryId);
       
   986 	
       
   987 	iMsvApi->CleanUserFoldersL();
       
   988 	
       
   989 	iChangeFinder->ResetL();
       
   990 	
       
   991     User::RequestComplete(iCallerStatus, KErrNone);
       
   992     
       
   993     LOGGER_LEAVEFN("CSmsDataStore::DoDeleteAllItemsL");
       
   994 	}
       
   995 
       
   996 
       
   997 // -----------------------------------------------------------------------------
       
   998 // CSmsDataStore::DoHasSyncHistory
       
   999 // This method returns ETrue if Data Store has history information. 
       
  1000 // Slow-sync will be used if Data Store does not have history information.
       
  1001 // -----------------------------------------------------------------------------
       
  1002 TBool CSmsDataStore::DoHasSyncHistory() const
       
  1003 	{
       
  1004 	LOGGER_WRITE_1("CSmsDataStore::DoHasSyncHistory return %d", (TInt)iHasHistory );	
       
  1005 	
       
  1006 	// iHasHistory is initialized in DoOpenL method
       
  1007 	return iHasHistory;
       
  1008 	}
       
  1009 
       
  1010 // -----------------------------------------------------------------------------
       
  1011 // CSmsDataStore::DoAddedItems
       
  1012 // This method returns UIDs of added items. Those items are added after previous
       
  1013 // synchronization with current synchronization relationship. 
       
  1014 // -----------------------------------------------------------------------------
       
  1015 const MSmlDataItemUidSet& CSmsDataStore::DoAddedItems() const
       
  1016 	{
       
  1017 	LOGGER_ENTERFN("CSmsDataStore::DoAddedItems");	
       
  1018 	
       
  1019 	// Ensure that we're in a proper state
       
  1020 	if (iCurrentState != ESmsOpenAndWaiting)
       
  1021 		{
       
  1022 		LOGGER_WRITE_1("CSmsDataStore::DoAddedItems, invalid state %d.", iCurrentState);
       
  1023 		}
       
  1024 		
       
  1025 	TInt error(KErrNone);
       
  1026 
       
  1027 	// Clear new-items array
       
  1028 	iNewItems->Reset();
       
  1029 	
       
  1030     // Search for new items
       
  1031     TRAP( error, iChangeFinder->FindNewItemsL(*iNewItems) );
       
  1032     if ( error != KErrNone )
       
  1033         {
       
  1034         LOGGER_WRITE_1("CSmsDataStore::DoAddedItems, iChangeFinder->FindNewItemsL leaved with %d.", error);
       
  1035         }
       
  1036 	
       
  1037 	LOGGER_WRITE_1("New item count: %d.", iNewItems->ItemCount());
       
  1038 	LOGGER_LEAVEFN("CSmsDataStore::DoAddedItems");		
       
  1039 	
       
  1040 	return *iNewItems;
       
  1041 	}
       
  1042 
       
  1043 // -----------------------------------------------------------------------------
       
  1044 // CSmsDataStore::DoDeletedItems
       
  1045 //
       
  1046 // -----------------------------------------------------------------------------
       
  1047 const MSmlDataItemUidSet& CSmsDataStore::DoDeletedItems() const
       
  1048 	{
       
  1049 	LOGGER_ENTERFN("CSmsDataStore::DoDeletedItemsL");	
       
  1050 	
       
  1051 	// Ensure that we're in a proper state
       
  1052 	if (iCurrentState != ESmsOpenAndWaiting)
       
  1053 	    {
       
  1054 	    LOGGER_WRITE_1("CSmsDataStore::DoDeletedItems, invalid state %d.", iCurrentState);
       
  1055 	    }
       
  1056 
       
  1057 	TInt error(KErrNone);
       
  1058 	
       
  1059 	// Clear deleted-items array
       
  1060 	iDeletedItems->Reset();
       
  1061 	
       
  1062     // Search for deleted items
       
  1063     TRAP( error, iChangeFinder->FindDeletedItemsL(*iDeletedItems) );
       
  1064     if ( error != KErrNone )
       
  1065         {
       
  1066         LOGGER_WRITE_1("CSmsDataStore::DoDeletedItems, iChangeFinder->FindDeletedItemsL leaved with %d.", error);
       
  1067         }
       
  1068 	
       
  1069 	
       
  1070 	LOGGER_WRITE_1("Deleted item count: %d.", iDeletedItems->ItemCount());
       
  1071 	LOGGER_LEAVEFN("CSmsDataStore::DoDeletedItemsL");
       
  1072 	return *iDeletedItems;
       
  1073 	}
       
  1074 
       
  1075 // -----------------------------------------------------------------------------
       
  1076 // CSmsDataStore::DoSoftDeletedItems
       
  1077 // Not directly supported, equals to "hard" delete
       
  1078 // -----------------------------------------------------------------------------
       
  1079 const MSmlDataItemUidSet& CSmsDataStore::DoSoftDeletedItems() const
       
  1080 	{
       
  1081 	TRACE_FUNC;
       
  1082 	
       
  1083     // Return empty array as a result
       
  1084     iSoftDeletedItems->Reset();
       
  1085 	return *iSoftDeletedItems;
       
  1086 	}
       
  1087 
       
  1088 // -----------------------------------------------------------------------------
       
  1089 // CSmsDataStore::DoModifiedItems
       
  1090 // Finds all modified items in the data store
       
  1091 // -----------------------------------------------------------------------------
       
  1092 const MSmlDataItemUidSet& CSmsDataStore::DoModifiedItems() const
       
  1093 	{
       
  1094 	LOGGER_ENTERFN("CSmsDataStore::DoModifiedItems");	
       
  1095 	
       
  1096 	// Ensure that we're in a proper state
       
  1097 	if (iCurrentState != ESmsOpenAndWaiting)
       
  1098 		{
       
  1099 		LOGGER_WRITE_1("CSmsDataStore::DoModifiedItems, invalid state %d.", iCurrentState);
       
  1100 		}
       
  1101 
       
  1102 	TInt error(KErrNone);
       
  1103 
       
  1104 	// Clear updated-items array
       
  1105 	iUpdatedItems->Reset();
       
  1106 	
       
  1107     // Search for updated items
       
  1108     TRAP( error, iChangeFinder->FindChangedItemsL(*iUpdatedItems) )
       
  1109     if ( error != KErrNone )
       
  1110         {
       
  1111         LOGGER_WRITE_1("CSmsDataStore::DoModifiedItems, iChangeFinder->FindChangedItemsL leaved with %d.", error);
       
  1112         }
       
  1113     else
       
  1114         {
       
  1115         TRAP( error, iChangeFinder->FindMovedItemsL(*iUpdatedItems) );
       
  1116         if( error != KErrNone )
       
  1117             {
       
  1118             LOGGER_WRITE_1("CSmsDataStore::DoModifiedItems, iChangeFinder->FindMovedItemsL leaved with %d.", error);
       
  1119             }		    
       
  1120         }
       
  1121 	
       
  1122 	LOGGER_WRITE_1("Modified item count: %d.", iUpdatedItems->ItemCount());
       
  1123 	LOGGER_LEAVEFN("CSmsDataStore::DoModifiedItems");		
       
  1124 	return *iUpdatedItems;
       
  1125 	}
       
  1126 
       
  1127 // -----------------------------------------------------------------------------
       
  1128 // CSmsDataStore::DoMovedItems
       
  1129 // Moved items not supported (handled as replaced items)
       
  1130 // -----------------------------------------------------------------------------
       
  1131 const MSmlDataItemUidSet& CSmsDataStore::DoMovedItems() const
       
  1132 	{
       
  1133 	TRACE_FUNC;	
       
  1134 	
       
  1135 	// Clear moved-items array
       
  1136 	iMovedItems->Reset();
       
  1137 	
       
  1138 	return *iMovedItems;	
       
  1139 	}
       
  1140 
       
  1141 // -----------------------------------------------------------------------------
       
  1142 // CSmsDataStore::DoResetChangeInfoL
       
  1143 // Resets change history in the data store. All content is considered
       
  1144 // new in the data store point of view.
       
  1145 // -----------------------------------------------------------------------------
       
  1146 void CSmsDataStore::DoResetChangeInfoL(TRequestStatus& aStatus)
       
  1147 	{
       
  1148 	LOGGER_ENTERFN("CSmsDataStore::DoResetChangeInfoL");	
       
  1149 	
       
  1150 	iCallerStatus = &aStatus;
       
  1151 	*iCallerStatus = KRequestPending;
       
  1152 	
       
  1153     // Check that we're in proper state
       
  1154 	if (iCurrentState != ESmsOpenAndWaiting) 
       
  1155 		{
       
  1156 		LOGGER_WRITE_1("CSmsDataStore::DoResetChangeInfoL, invalid state %d.", iCurrentState);
       
  1157 		}	
       
  1158 			
       
  1159 	// Reset change info in ChangeFinder
       
  1160 	iChangeFinder->ResetL();
       
  1161 	iHasHistory = EFalse;
       
  1162 	
       
  1163     // Signal we're done
       
  1164     User::RequestComplete(iCallerStatus, KErrNone);	
       
  1165     
       
  1166     LOGGER_LEAVEFN("CSmsDataStore::DoResetChangeInfoL");
       
  1167 	}
       
  1168 		
       
  1169 // -----------------------------------------------------------------------------
       
  1170 // CSmsDataStore::DoCommitChangeInfoL
       
  1171 // Commits change info. These items are no longer reported, when change
       
  1172 // information is being queried.
       
  1173 // -----------------------------------------------------------------------------
       
  1174 void CSmsDataStore::DoCommitChangeInfoL(TRequestStatus& aStatus, const MSmlDataItemUidSet& aItems)
       
  1175 	{
       
  1176 	LOGGER_ENTERFN("CSmsDataStore::DoCommitChangeInfoL(MSmlDataItemUidSet)");	
       
  1177 	LOGGER_WRITE_1("Item count: %d", aItems.ItemCount());
       
  1178 	
       
  1179 	iCallerStatus = &aStatus;
       
  1180     *iCallerStatus = KRequestPending;
       
  1181     
       
  1182     // Ensure that we're in a proper state
       
  1183     if (iCurrentState != ESmsOpenAndWaiting) 
       
  1184 	    {
       
  1185 		LOGGER_WRITE_1("CSmsDataStore::DoCommitChangeInfoL, invalid state %d.", iCurrentState);
       
  1186 		}
       
  1187 
       
  1188 	// Notify ChangeFinder
       
  1189     iChangeFinder->CommitChangesL(aItems);
       
  1190     iHasHistory = ETrue;
       
  1191 	    
       
  1192 	// Signal we're done
       
  1193 	User::RequestComplete(iCallerStatus, KErrNone);
       
  1194 	    
       
  1195 	LOGGER_LEAVEFN("CSmsDataStore::DoCommitChangeInfoL");
       
  1196 	}
       
  1197 		
       
  1198 	
       
  1199 // -----------------------------------------------------------------------------
       
  1200 // CSmsDataStore::DoCommitChangeInfoL
       
  1201 // Commits change info. There is no more nothing to report when change
       
  1202 // information is being queried. 
       
  1203 // -----------------------------------------------------------------------------
       
  1204 void CSmsDataStore::DoCommitChangeInfoL(TRequestStatus& aStatus)
       
  1205 	{
       
  1206 	LOGGER_ENTERFN("CSmsDataStore::DoCommitChangeInfoL");
       
  1207 	
       
  1208 	iCallerStatus = &aStatus;
       
  1209 	*iCallerStatus = KRequestPending;
       
  1210 	
       
  1211 	// Ensure that we're in a proper state
       
  1212 	if (iCurrentState != ESmsOpenAndWaiting) 
       
  1213 	    {
       
  1214 		LOGGER_WRITE_1("CSmsDataStore::DoCommitChangeInfoL, invalid state %d.", iCurrentState);
       
  1215 		}
       
  1216 	
       
  1217 	// Notify ChangeFinder
       
  1218 	iChangeFinder->CommitChangesL();
       
  1219 	iHasHistory = ETrue;
       
  1220 	    
       
  1221 	// Signal we're done
       
  1222 	User::RequestComplete(iCallerStatus, KErrNone);
       
  1223 	
       
  1224 	LOGGER_LEAVEFN("CSmsDataStore::DoCommitChangeInfoL");
       
  1225 	}
       
  1226 		
       
  1227 
       
  1228 // -----------------------------------------------------------------------------
       
  1229 // CSmsDataStore::RegisterSnapshotL
       
  1230 // Sets Changefinder to compare against current message store content
       
  1231 // -----------------------------------------------------------------------------
       
  1232 void CSmsDataStore::RegisterSnapshotL() const
       
  1233 	{
       
  1234 	LOGGER_ENTERFN("CSmsDataStore::RegisterSnapshotL");
       
  1235 	
       
  1236     CSnapshotArray* snapshot = new (ELeave) CSnapshotArray( KSnapshotGranularity );
       
  1237     CleanupStack::PushL(snapshot);
       
  1238 	
       
  1239 	// Use only standard folders (outbox isn't synchronized)
       
  1240 	LOGGER_WRITE( "KMsvGlobalInBoxIndexEntryId" );
       
  1241 	RegisterFolderL(snapshot, KMsvGlobalInBoxIndexEntryId);
       
  1242 	LOGGER_WRITE( "KMsvDraftEntryId" );
       
  1243 	RegisterFolderL(snapshot, KMsvDraftEntryId);
       
  1244 	LOGGER_WRITE( "KMsvSentEntryId" );
       
  1245 	RegisterFolderL(snapshot, KMsvSentEntryId);
       
  1246 	LOGGER_WRITE( "KMsvGlobalOutBoxIndexEntryId" );
       
  1247 	RegisterFolderL(snapshot, KMsvGlobalOutBoxIndexEntryId);
       
  1248 	RegisterUserFoldersL(snapshot);
       
  1249 	
       
  1250 	// Set new snapshot to compare against
       
  1251 	iChangeFinder->SetNewSnapshot(snapshot);
       
  1252 
       
  1253 	// Changefinder takes ownership of the snapshot
       
  1254 	CleanupStack::Pop();
       
  1255 	
       
  1256 	LOGGER_LEAVEFN("CSmsDataStore::RegisterSnapshotL");	
       
  1257 	}
       
  1258 
       
  1259 // -----------------------------------------------------------------------------
       
  1260 // CSmsDataStore::RegisterFolderL
       
  1261 // Adds a single folder into the snapshot array
       
  1262 // -----------------------------------------------------------------------------
       
  1263 TInt CSmsDataStore::RegisterFolderL(CSnapshotArray* aSnapshot, const TMsvId& aId) const
       
  1264 	{
       
  1265 	LOGGER_ENTERFN("CSmsDataStore::RegisterFolderL");	
       
  1266 	
       
  1267 	CMsvSession* msvSession = iMsvApi->MsvSessionL();
       
  1268 
       
  1269 	// Get the folder	
       
  1270 	CMsvEntry* msvEntry = msvSession->GetEntryL(aId);
       
  1271 	CleanupStack::PushL(msvEntry);
       
  1272 	
       
  1273 	// Find all of it's childs
       
  1274 	CMsvEntrySelection* messages = msvEntry->ChildrenWithTypeL(KUidMsvMessageEntry);
       
  1275 	CleanupStack::PopAndDestroy(); // msvEntry
       
  1276 	CleanupStack::PushL(messages);
       
  1277 	
       
  1278     TMsvId id;
       
  1279     TMsvEntry msg;
       
  1280     LOGGER_WRITE_1( "messages count %d", messages->Count() );
       
  1281 	for(TInt index=0; index<messages->Count(); index++)
       
  1282 		{
       
  1283 		TInt result = msvSession->GetEntry(messages->At(index), id, msg);
       
  1284 		User::LeaveIfError(result);
       
  1285 		
       
  1286 		// We're only interested about the SMS content
       
  1287 		if(msg.iMtm == KUidMsgTypeSMS)
       
  1288 			{
       
  1289 			// Create snapshot item
       
  1290 			TKeyArrayFix key(iKey);
       
  1291 			TSnapshotItem item((TUint) msg.Id(), msg.Parent(), msg.Unread());
       
  1292 			
       
  1293 			item.SetLastChangedDate(msg.iDate);
       
  1294 			LOGGER_WRITE_1( "item id %d", msg.Id() );
       
  1295 			// Add to snapshot
       
  1296 			aSnapshot->InsertIsqL(item, key);
       
  1297 			}
       
  1298 	    else
       
  1299 	        {
       
  1300 	        LOGGER_WRITE("Wrong type");
       
  1301 	        }
       
  1302 		}
       
  1303 
       
  1304 	CleanupStack::PopAndDestroy(); // messages
       
  1305 	
       
  1306     LOGGER_LEAVEFN("CSmsDataStore::RegisterFolderL");	
       
  1307 
       
  1308 	return KErrNone;
       
  1309 	}
       
  1310 	
       
  1311 // -----------------------------------------------------------------------------
       
  1312 // CSmsDataStore::RegisterUserFoldersL
       
  1313 // Adds user folder messages into the snapshot array
       
  1314 // -----------------------------------------------------------------------------
       
  1315 TInt CSmsDataStore::RegisterUserFoldersL(CSnapshotArray* aSnapshot) const
       
  1316     {
       
  1317  	LOGGER_ENTERFN("CSmsDataStore::RegisterUserFoldersL");	   
       
  1318     
       
  1319     CMsvSession* msvSession = iMsvApi->MsvSessionL();
       
  1320     
       
  1321     // Get the folder	
       
  1322 	CMsvEntry* msvEntry = msvSession->GetEntryL(KMsvMyFoldersEntryIdValue);
       
  1323     CleanupStack::PushL(msvEntry);
       
  1324     
       
  1325     // Find all of it's childs
       
  1326     CMsvEntrySelection* folders = msvEntry->ChildrenWithTypeL( KUidMsvFolderEntry );
       
  1327     CleanupStack::PopAndDestroy( msvEntry ); 
       
  1328     CleanupStack::PushL( folders );
       
  1329     LOGGER_WRITE_1("Folders: %d", folders->Count());
       
  1330     for ( TInt index = 0; index < folders->Count(); index++ )
       
  1331         {
       
  1332         TMsvId folderId = folders->At(index);
       
  1333         
       
  1334         if ( folderId != KMsvMyFoldersTemplatesFolderId )
       
  1335             {
       
  1336             TMsvId service;
       
  1337             TMsvEntry folderEntry;
       
  1338             TInt result = msvSession->GetEntry(folderId, service, folderEntry);
       
  1339             User::LeaveIfError( result );
       
  1340             
       
  1341             TKeyArrayFix key(iKey);
       
  1342             TBool unread(EFalse);
       
  1343             TSnapshotItem item( (TUint) folderId, folderEntry.Parent(), unread );
       
  1344             item.SetLastChangedDate( folderEntry.iDate );
       
  1345             item.SetFolderNameL( folderEntry.iDetails );
       
  1346             
       
  1347             aSnapshot->InsertIsqL( item, key );
       
  1348             
       
  1349             RegisterFolderL( aSnapshot, folderId );
       
  1350             }
       
  1351         }
       
  1352     
       
  1353     CleanupStack::PopAndDestroy( folders );
       
  1354 	
       
  1355 	// Register also SMS messages directly under My Folders
       
  1356     RegisterFolderL( aSnapshot, KMsvMyFoldersEntryIdValue );
       
  1357     
       
  1358 	LOGGER_LEAVEFN("CSmsDataStore::RegisterUserFoldersL");	   
       
  1359     
       
  1360     return KErrNone;
       
  1361     }
       
  1362