omads/omadsextensions/adapters/contactsgroup/src/contactsgrpdatastore.cpp
branchRCL_3
changeset 52 4f0867e42d62
parent 51 8e7494275d3a
child 56 3e6957da2ff8
equal deleted inserted replaced
51:8e7494275d3a 52:4f0867e42d62
     1 /*
       
     2 * Copyright (c) 2009-2010 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 <sysutil.h> 
       
    20 #include <cntfldst.h>
       
    21 
       
    22 #include "contactsgrpdatastore.h"
       
    23 #include "contactsgrpconverter.h"
       
    24 #include "changefinder.h"
       
    25 #include "contactsgrpdataproviderdefs.h"
       
    26 #include "logger.h"
       
    27 
       
    28 const TInt KDefaultBufferSize = 1024;
       
    29 const TInt KDataBufferNotReady = -1;
       
    30 // -----------------------------------------------------------------------------
       
    31 // CContactsGrpDataStore::CContactsGrpDataStore
       
    32 // C++ default constructor can NOT contain any code, that might leave.
       
    33 // -----------------------------------------------------------------------------
       
    34 CContactsGrpDataStore::CContactsGrpDataStore() :
       
    35     iKey( TKeyArrayFix( _FOFF( TNSmlSnapshotItem, ItemId() ), ECmpTInt ) )
       
    36     {
       
    37     TRACE_FUNC;
       
    38     }
       
    39     
       
    40 // -----------------------------------------------------------------------------
       
    41 // CContactsGrpDataStore::ConstructL
       
    42 // Symbian 2nd phase constructor, can leave.
       
    43 // -----------------------------------------------------------------------------    
       
    44 void CContactsGrpDataStore::ConstructL()
       
    45     {
       
    46     TRACE_FUNC_ENTRY;
       
    47     
       
    48     User::LeaveIfError( iFs.Connect() );
       
    49     
       
    50     iNewItems       = new ( ELeave ) CNSmlDataItemUidSet;
       
    51     iDeletedItems   = new ( ELeave ) CNSmlDataItemUidSet;
       
    52     iUpdatedItems   = new ( ELeave ) CNSmlDataItemUidSet;
       
    53     iEmptyList      = new ( ELeave ) CNSmlDataItemUidSet;
       
    54     
       
    55     iConverter = CContactsGrpConverter::NewL();
       
    56     
       
    57     TRACE_FUNC_EXIT;
       
    58     }
       
    59     
       
    60 // -----------------------------------------------------------------------------
       
    61 // CContactsGrpDataStore::~CContactsGrpDataStore
       
    62 // Destructor
       
    63 // -----------------------------------------------------------------------------    
       
    64 CContactsGrpDataStore::~CContactsGrpDataStore()
       
    65     {
       
    66     TRACE_FUNC_ENTRY;
       
    67 
       
    68     delete iDataBuffer;
       
    69     delete iNewItems;
       
    70     delete iDeletedItems;
       
    71     delete iUpdatedItems;
       
    72     delete iEmptyList;
       
    73     
       
    74     if ( iChangeFinder )
       
    75         {
       
    76         TRAPD( error, iChangeFinder->CloseL() );
       
    77         if ( error != KErrNone )
       
    78             {
       
    79             LOGGER_WRITE_1( "iChangeFinder->CloseL() leaved with %d", error );
       
    80             }
       
    81         }
       
    82     delete iChangeFinder;
       
    83     
       
    84     delete iConverter;
       
    85     
       
    86     delete iContactsDb;
       
    87     
       
    88     iFs.Close();
       
    89     TRACE_FUNC_EXIT;
       
    90     }
       
    91 
       
    92 // -----------------------------------------------------------------------------
       
    93 // CContactsGrpDataStore::NewL
       
    94 // Two-phased constructor.
       
    95 // -----------------------------------------------------------------------------
       
    96 CContactsGrpDataStore* CContactsGrpDataStore::NewL()
       
    97     {
       
    98     TRACE_FUNC_ENTRY;
       
    99     CContactsGrpDataStore* self = CContactsGrpDataStore::NewLC();
       
   100     CleanupStack::Pop( self );
       
   101     TRACE_FUNC_EXIT;
       
   102     return self;
       
   103     }
       
   104 
       
   105 // -----------------------------------------------------------------------------
       
   106 // CContactsGrpDataStore::NewLC
       
   107 // Two-phased constructor.
       
   108 // -----------------------------------------------------------------------------
       
   109 CContactsGrpDataStore* CContactsGrpDataStore::NewLC()
       
   110     {
       
   111     TRACE_FUNC_ENTRY;
       
   112     CContactsGrpDataStore* self = new ( ELeave ) CContactsGrpDataStore();
       
   113     CleanupStack::PushL( self );
       
   114     self->ConstructL();
       
   115     TRACE_FUNC_EXIT;
       
   116     return self;
       
   117     }
       
   118 
       
   119 // -----------------------------------------------------------------------------
       
   120 // CContactsGrpDataStore::DoOpenL
       
   121 // Opens database.
       
   122 // -----------------------------------------------------------------------------
       
   123 void CContactsGrpDataStore::DoOpenL( const TDesC& /*aStoreName*/,
       
   124     MSmlSyncRelationship& aContext, TRequestStatus& aStatus )
       
   125     {
       
   126     TRACE_FUNC_ENTRY;
       
   127     
       
   128     iCallerStatus = &aStatus;           
       
   129     *iCallerStatus = KRequestPending;
       
   130     
       
   131     if ( iContactsDb )
       
   132         {
       
   133         // already opened
       
   134         User::RequestComplete( iCallerStatus, KErrInUse );
       
   135         LOGGER_WRITE( "CContactsGrpDataStore::DoOpenL failed with KErrInUse." );
       
   136         return;
       
   137         }
       
   138     
       
   139     // Create ChangeFinder
       
   140     if ( iChangeFinder )
       
   141         {
       
   142         delete iChangeFinder;
       
   143         iChangeFinder = NULL;
       
   144         }
       
   145     iChangeFinder = CChangeFinder::NewL( aContext, iKey, iHasHistory );
       
   146     
       
   147     iContactsDb = CContactDatabase::OpenL();
       
   148     
       
   149     RegisterSnapshotL();
       
   150     
       
   151     User::RequestComplete( iCallerStatus, KErrNone );
       
   152     TRACE_FUNC_EXIT;
       
   153     }
       
   154 
       
   155 
       
   156 // -----------------------------------------------------------------------------
       
   157 // CContactsGrpDataStore::DoCancelRequest
       
   158 // Not supported, does nothing.
       
   159 // -----------------------------------------------------------------------------
       
   160 void CContactsGrpDataStore::DoCancelRequest()
       
   161     {
       
   162     TRACE_FUNC;
       
   163     }
       
   164 
       
   165 // -----------------------------------------------------------------------------
       
   166 // CContactsGrpDataStore::DoStoreName
       
   167 // Returns the name of the DataStore
       
   168 // -----------------------------------------------------------------------------
       
   169 const TDesC& CContactsGrpDataStore::DoStoreName() const
       
   170     {
       
   171     TRACE_FUNC;
       
   172     
       
   173     if ( iContactsDb )
       
   174         {
       
   175         return KContactsGrpStoreName;
       
   176         }
       
   177     else
       
   178         {
       
   179         return KNullDesC;
       
   180         }
       
   181     }
       
   182     
       
   183 // -----------------------------------------------------------------------------
       
   184 // CContactsGrpDataStore::DoBeginTransactionL
       
   185 // Transactions are not supported.
       
   186 // -----------------------------------------------------------------------------    
       
   187 void CContactsGrpDataStore::DoBeginTransactionL()
       
   188     {
       
   189     TRACE_FUNC;
       
   190     User::Leave( KErrNotSupported );
       
   191     }
       
   192 
       
   193 // -----------------------------------------------------------------------------
       
   194 // CContactsGrpDataStore::DoCommitTransactionL
       
   195 // Transactions are not supported.
       
   196 // -----------------------------------------------------------------------------
       
   197 void CContactsGrpDataStore::DoCommitTransactionL( TRequestStatus& aStatus )
       
   198     {
       
   199     TRACE_FUNC;
       
   200     iCallerStatus = &aStatus;
       
   201     User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   202     }
       
   203 
       
   204 // -----------------------------------------------------------------------------
       
   205 // CContactsGrpDataStore::DoRevertTransaction
       
   206 // Transactions are not supported.
       
   207 // -----------------------------------------------------------------------------
       
   208 void CContactsGrpDataStore::DoRevertTransaction( TRequestStatus& aStatus )
       
   209     {
       
   210     TRACE_FUNC;
       
   211     iCallerStatus = &aStatus;
       
   212     User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   213     }
       
   214 
       
   215 // -----------------------------------------------------------------------------
       
   216 // CContactsGrpDataStore::DoBeginBatchL
       
   217 // Batching is not supported.
       
   218 // -----------------------------------------------------------------------------
       
   219 void CContactsGrpDataStore::DoBeginBatchL()
       
   220     {
       
   221     TRACE_FUNC;
       
   222     User::Leave( KErrNotSupported );
       
   223     }
       
   224 
       
   225 // -----------------------------------------------------------------------------
       
   226 // CContactsGrpDataStore::DoCommitBatchL
       
   227 // Batching is not supported
       
   228 // -----------------------------------------------------------------------------
       
   229 void CContactsGrpDataStore::DoCommitBatchL( RArray<TInt>& /*aResultArray*/, TRequestStatus& aStatus )
       
   230     {
       
   231     TRACE_FUNC;
       
   232     iCallerStatus = &aStatus;
       
   233     User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   234     }
       
   235 
       
   236 // -----------------------------------------------------------------------------
       
   237 // CContactsGrpDataStore::DoCancelBatch
       
   238 // Batching is not supported
       
   239 // -----------------------------------------------------------------------------
       
   240 void CContactsGrpDataStore::DoCancelBatch()
       
   241     {
       
   242     TRACE_FUNC;
       
   243     }
       
   244 
       
   245 // -----------------------------------------------------------------------------
       
   246 // CContactsGrpDataStore::DoSetRemoteStoreFormatL
       
   247 // Not supported
       
   248 // -----------------------------------------------------------------------------
       
   249 void CContactsGrpDataStore::DoSetRemoteStoreFormatL( const CSmlDataStoreFormat& /*aServerDataStoreFormat*/ )
       
   250     {
       
   251     TRACE_FUNC;
       
   252     }
       
   253     
       
   254 // -----------------------------------------------------------------------------
       
   255 // CContactsGrpDataStore::DoSetRemoteMaxObjectSize
       
   256 // Not supported
       
   257 // -----------------------------------------------------------------------------
       
   258 void CContactsGrpDataStore::DoSetRemoteMaxObjectSize( TInt /*aServerMaxObjectSize*/ )
       
   259     {
       
   260     TRACE_FUNC;
       
   261     }
       
   262 
       
   263 
       
   264 // -----------------------------------------------------------------------------
       
   265 // CContactsGrpDataStore::DoMaxObjectSize
       
   266 // Reads the maximum object size from the central repository
       
   267 // -----------------------------------------------------------------------------
       
   268 TInt CContactsGrpDataStore::DoMaxObjectSize() const
       
   269     {
       
   270     TRACE_FUNC;
       
   271     return 0; // no limit
       
   272     }
       
   273 
       
   274 // -----------------------------------------------------------------------------
       
   275 // CContactsGrpDataStore::DoOpenItemL
       
   276 // Opens item in the DataStore, reads it (either completely or partially) 
       
   277 // to the temporary buffer where it can be later read to the remote database.
       
   278 // -----------------------------------------------------------------------------
       
   279 void CContactsGrpDataStore::DoOpenItemL(
       
   280     TSmlDbItemUid aUid, 
       
   281     TBool& aFieldChange, 
       
   282     TInt& aSize, 
       
   283     TSmlDbItemUid& aParent, 
       
   284     TDes8& aMimeType, 
       
   285     TDes8& aMimeVer, 
       
   286     TRequestStatus& aStatus )
       
   287     {
       
   288     TRACE_FUNC_ENTRY;
       
   289     LOGGER_WRITE_1( "aUid: %d", aUid );
       
   290     
       
   291     iCallerStatus = &aStatus;
       
   292     *iCallerStatus = KRequestPending;
       
   293     
       
   294     aFieldChange = EFalse;
       
   295     aParent = KErrNotFound;
       
   296     
       
   297     delete iDataBuffer;
       
   298     iDataBuffer = NULL;
       
   299     
       
   300     if ( !iContactsDb )
       
   301         {
       
   302         User::Leave( KErrNotReady );
       
   303         }
       
   304     
       
   305     iDataBuffer = CBufFlat::NewL( KDefaultBufferSize ); 
       
   306     iReaderPosition = 0;
       
   307     
       
   308     CContactItem* item = iContactsDb->ReadContactLC( aUid );
       
   309     if ( item->Type() != KUidContactGroup )
       
   310         {
       
   311         CleanupStack::PopAndDestroy( item );
       
   312         User::Leave( KErrNotFound );
       
   313         }
       
   314 
       
   315     iConverter->ImportDbItemL( *static_cast<CContactGroup*>(item) );
       
   316     
       
   317     CleanupStack::PopAndDestroy( item );
       
   318     
       
   319     iConverter->ExportVCardL( *iDataBuffer );
       
   320     iConverter->ResetL();
       
   321     aSize = iDataBuffer->Size();
       
   322     
       
   323     // Set mime type to correct one
       
   324     AssignString( aMimeType, KContactsGrpItemMimeType );
       
   325     AssignString( aMimeVer, KContactsGrpItemMimeVersion );
       
   326     
       
   327     User::RequestComplete( iCallerStatus, KErrNone );   
       
   328     iCurrentState = EContactGrpOpening;
       
   329     
       
   330     TRACE_FUNC_EXIT;   
       
   331     }
       
   332 
       
   333 // -----------------------------------------------------------------------------
       
   334 // CContactsGrpDataStore::DoCreateItemL
       
   335 // Create new item to the message store.
       
   336 // Return the id number of the newly created item
       
   337 // -----------------------------------------------------------------------------
       
   338 void CContactsGrpDataStore::DoCreateItemL(
       
   339     TSmlDbItemUid& aUid, 
       
   340     TInt aSize, 
       
   341     TSmlDbItemUid /*aParent*/, 
       
   342     const TDesC8& /*aMimeType*/, 
       
   343     const TDesC8& /*aMimeVer*/, 
       
   344     TRequestStatus& aStatus )
       
   345     {
       
   346     TRACE_FUNC_ENTRY;
       
   347     iCallerStatus = &aStatus;
       
   348     *iCallerStatus = KRequestPending;
       
   349     
       
   350     // Ensure that we're in a proper state
       
   351     if ( iCurrentState != EOpenAndWaiting )
       
   352         {
       
   353         LOGGER_WRITE_1( "Warning: Unexpected current state: %d", iCurrentState );
       
   354         }
       
   355         
       
   356     if ( !iContactsDb )
       
   357         {
       
   358         LOGGER_WRITE( "iContactsDb not ready" );
       
   359         User::Leave( KErrNotReady );
       
   360         }
       
   361     
       
   362     // Ensure that we've got enough disk space for the item
       
   363     if ( SysUtil::DiskSpaceBelowCriticalLevelL( &iFs, aSize, EDriveC ) )
       
   364         {
       
   365         User::RequestComplete( iCallerStatus, KErrDiskFull );
       
   366         LOGGER_WRITE( "SysUtil::DiskSpaceBelowCriticalLevelL failed with KErrDiskFull." );
       
   367         return;
       
   368         }
       
   369     
       
   370     // item uid is updated when groups is saved to db.
       
   371     iCurrentItem = &aUid; 
       
   372     // Save current operation-state so we know what operation
       
   373     // is needed to do on DoCommitItemL
       
   374     iCurrentState = EContactGrpCreating;
       
   375                 
       
   376     delete iDataBuffer;
       
   377     iDataBuffer = NULL;
       
   378     iDataBuffer = CBufFlat::NewL( KDefaultBufferSize );
       
   379     iWriterPosition = 0;
       
   380     
       
   381     User::RequestComplete( iCallerStatus, KErrNone );  
       
   382     TRACE_FUNC_EXIT;    
       
   383     }
       
   384 
       
   385 // -----------------------------------------------------------------------------
       
   386 // CContactsGrpDataStore::DoReplaceItemL
       
   387 // Begin the replace operation, ensure that the item really exists
       
   388 // -----------------------------------------------------------------------------
       
   389 void CContactsGrpDataStore::DoReplaceItemL(
       
   390     TSmlDbItemUid aUid, 
       
   391     TInt aSize, 
       
   392     TSmlDbItemUid /*aParent*/,
       
   393     TBool /*aFieldChange*/, 
       
   394     TRequestStatus& aStatus )
       
   395     {
       
   396     TRACE_FUNC_ENTRY;
       
   397     LOGGER_WRITE_1("aUid: %d", aUid);
       
   398     
       
   399     iCallerStatus = &aStatus;
       
   400     *iCallerStatus = KRequestPending;
       
   401     
       
   402     if ( !iContactsDb )
       
   403         {
       
   404         LOGGER_WRITE( "iContactsDb not ready" );
       
   405         User::Leave( KErrNotReady );
       
   406         }
       
   407         
       
   408     // Ensure that we've got enough disk space for the item
       
   409     if ( SysUtil::DiskSpaceBelowCriticalLevelL( &iFs, aSize, EDriveC ) )
       
   410         {
       
   411         User::RequestComplete( iCallerStatus, KErrDiskFull );
       
   412         LOGGER_WRITE( "SysUtil::DiskSpaceBelowCriticalLevelL failed with KErrDiskFull." );
       
   413         return;
       
   414         }
       
   415     
       
   416     // check that item exist and is Group-type
       
   417     CContactItem* item = iContactsDb->ReadContactLC( aUid );
       
   418     if ( item->Type() != KUidContactGroup )
       
   419         {
       
   420         CleanupStack::PopAndDestroy( item );
       
   421         User::Leave( KErrNotFound );
       
   422         }
       
   423     CleanupStack::PopAndDestroy( item );
       
   424     
       
   425     // init databuffer
       
   426     delete iDataBuffer;
       
   427     iDataBuffer = NULL;
       
   428     iDataBuffer = CBufFlat::NewL( KDefaultBufferSize );
       
   429     iWriterPosition = 0;
       
   430     
       
   431     // Save current item, so we know what item needs to be replaced
       
   432     iItemToBeReplaced = aUid;
       
   433     // Save current operation-state so we know what operation
       
   434     // is needed to do on DoCommitItemL
       
   435     iCurrentState = EContactGrpUpdating;
       
   436     
       
   437     User::RequestComplete( iCallerStatus, KErrNone );   
       
   438     
       
   439     TRACE_FUNC_EXIT;
       
   440     }
       
   441 
       
   442 // -----------------------------------------------------------------------------
       
   443 // CContactsGrpDataStore::DoReadItemL
       
   444 // Read specified amount of data from the temporary buffer
       
   445 // -----------------------------------------------------------------------------
       
   446 void CContactsGrpDataStore::DoReadItemL( TDes8& aBuffer )
       
   447     {
       
   448     TRACE_FUNC_ENTRY;
       
   449     
       
   450     if ( iCurrentState != EContactGrpOpening || !iDataBuffer )
       
   451         {
       
   452         LOGGER_WRITE_1( "Unexpected state %d", iCurrentState );
       
   453         User::Leave( KErrNotReady );
       
   454         }
       
   455         
       
   456     if ( iReaderPosition == KDataBufferNotReady )
       
   457         {
       
   458         LOGGER_WRITE( "No data to read" );
       
   459         User::Leave( KErrEof );
       
   460         }
       
   461     
       
   462     // Thiw is how much data there is left in the buffer    
       
   463     TInt left = iDataBuffer->Size() - iReaderPosition;
       
   464     
       
   465     if ( left > 0 )
       
   466         {
       
   467         // This is how much there's space in the destination buffer
       
   468         TInt destSize = aBuffer.MaxSize();
       
   469         
       
   470         // This is how much we can read
       
   471         TInt toRead = destSize < left ? destSize : left;
       
   472         
       
   473         // Read the data from the buffer, then update the position      
       
   474         iDataBuffer->Read( iReaderPosition, aBuffer, toRead );
       
   475         iReaderPosition += toRead;
       
   476         }
       
   477     else
       
   478         {
       
   479         iReaderPosition = KDataBufferNotReady;
       
   480         LOGGER_WRITE( "No data to read" );
       
   481         User::Leave( KErrEof );
       
   482         }   
       
   483         
       
   484     TRACE_FUNC_EXIT;
       
   485     }
       
   486 
       
   487 // -----------------------------------------------------------------------------
       
   488 // CContactsGrpDataStore::DoWriteItemL
       
   489 // Write specified amount of data to the temporary buffer
       
   490 // -----------------------------------------------------------------------------
       
   491 void CContactsGrpDataStore::DoWriteItemL( const TDesC8& aData )
       
   492     {
       
   493     TRACE_FUNC_ENTRY;
       
   494     
       
   495     if ( iCurrentState != EContactGrpCreating && iCurrentState != EContactGrpUpdating )
       
   496         {
       
   497         LOGGER_WRITE_1( "Unexpected current state: %d", iCurrentState );
       
   498         User::Leave( KErrNotReady );
       
   499         }
       
   500     
       
   501     // Calculate total size
       
   502     TInt totalSize = aData.Size() + iDataBuffer->Size();
       
   503 
       
   504     // Ensure that we've got enough disk space for the item
       
   505     if ( SysUtil::DiskSpaceBelowCriticalLevelL( &iFs, totalSize, EDriveC ) )
       
   506         {
       
   507         User::RequestComplete( iCallerStatus, KErrDiskFull );
       
   508         LOGGER_WRITE("SysUtil::DiskSpaceBelowCriticalLevelL failed with KErrDiskFull.");
       
   509         return;
       
   510         }
       
   511         
       
   512     // Add data to buffer       
       
   513     iDataBuffer->InsertL( iWriterPosition, aData );
       
   514     iWriterPosition += aData.Size();
       
   515     
       
   516     TRACE_FUNC_EXIT;
       
   517     }
       
   518 
       
   519 // -----------------------------------------------------------------------------
       
   520 // CContactsGrpDataStore::DoCommitItemL
       
   521 // Commits item from temporary buffer to the message store
       
   522 // -----------------------------------------------------------------------------
       
   523 void CContactsGrpDataStore::DoCommitItemL( TRequestStatus& aStatus )
       
   524     {
       
   525     TRACE_FUNC_ENTRY;
       
   526     iCallerStatus = &aStatus;
       
   527     *iCallerStatus = KRequestPending;
       
   528     
       
   529     // Check that we're in proper state
       
   530     if ( iCurrentState != EContactGrpCreating && iCurrentState != EContactGrpUpdating )
       
   531         {
       
   532         User::RequestComplete( iCallerStatus, KErrNotReady );
       
   533         LOGGER_WRITE_1( "Unexpected current state: %d", iCurrentState );
       
   534         return;
       
   535         }
       
   536         
       
   537     if ( iDataBuffer->Size() <= 0 )
       
   538         {
       
   539         User::RequestComplete( iCallerStatus, KErrNotReady );
       
   540         LOGGER_WRITE_1( "Data buffer has no data (%d)", iDataBuffer->Size() );
       
   541         return; 
       
   542         }
       
   543     
       
   544     if ( !iContactsDb )
       
   545         {
       
   546         LOGGER_WRITE( "iContactsDb not ready" );
       
   547         User::Leave( KErrNotReady );
       
   548         }
       
   549 
       
   550     iDataBuffer->Compress();
       
   551     iConverter->ImportVCardL( iDataBuffer->Ptr(0) );
       
   552     
       
   553     const CContactIdArray& contactArr = iConverter->ItemsContained();
       
   554     
       
   555     if ( iCurrentState == EContactGrpCreating )
       
   556         {
       
   557         *iCurrentItem = CreateNewGroupL( iConverter->GroupLabel(), contactArr );
       
   558         }
       
   559     else
       
   560         {
       
   561         ReplaceGroupL( iItemToBeReplaced, iConverter->GroupLabel(), contactArr);
       
   562         }
       
   563     iConverter->ResetL();
       
   564     
       
   565     // Destroy buffer
       
   566     delete iDataBuffer;
       
   567     iDataBuffer = NULL;
       
   568     iWriterPosition = 0;
       
   569     
       
   570     // Restore state and signal we're done
       
   571     iCurrentState = EOpenAndWaiting;
       
   572     User::RequestComplete( iCallerStatus, KErrNone );
       
   573     
       
   574     TRACE_FUNC_EXIT;
       
   575     }
       
   576 
       
   577 // -----------------------------------------------------------------------------
       
   578 // CContactsGrpDataStore::CreateNewGroupL
       
   579 // Creates new groupd to db.
       
   580 // -----------------------------------------------------------------------------
       
   581 TContactItemId CContactsGrpDataStore::CreateNewGroupL( const TDesC& aLabel,
       
   582         const CContactIdArray& aContactArray )
       
   583     {
       
   584     TRACE_FUNC_ENTRY;
       
   585     LOGGER_WRITE_1("aLabel: %S", &aLabel );
       
   586     
       
   587     // Check for duplicates
       
   588     if ( GroupNameExistsL( aLabel ) )
       
   589         {
       
   590         LOGGER_WRITE("Duplicate group name found, leave KErrAlreadyExists");
       
   591         User::Leave( KErrAlreadyExists );
       
   592         }
       
   593     
       
   594     CContactGroup* group =
       
   595         static_cast<CContactGroup*>
       
   596         (iContactsDb->CreateContactGroupLC( aLabel ));
       
   597     
       
   598     // Create new contact group
       
   599     
       
   600     TContactItemId groupId = group->Id();
       
   601     LOGGER_WRITE_1("new group id: %d", groupId);
       
   602     
       
   603     TBool partiallyUpdated(EFalse);
       
   604     TTime lastMod;
       
   605     lastMod.UniversalTime();
       
   606     TInt err(KErrNone);
       
   607     for ( TInt i=0; i<aContactArray.Count(); i++ )
       
   608         {
       
   609         LOGGER_WRITE_1("Add contact: %d", aContactArray[i] );
       
   610         TRAP( err, iContactsDb->AddContactToGroupL( aContactArray[i], groupId ));
       
   611         if ( err )
       
   612             {
       
   613             LOGGER_WRITE_2("Warning: AddContactToGroupL, contact: %d, err: %d", aContactArray[i], err);
       
   614             partiallyUpdated = ETrue;
       
   615             }
       
   616         else
       
   617             {
       
   618             // If succesfully added, update contact timestamp so contact sync sees those
       
   619             // contacts as changed ones.
       
   620             UpdateContactLastMod( aContactArray[i], lastMod );
       
   621             }
       
   622         }
       
   623     
       
   624     CleanupStack::PopAndDestroy( group );
       
   625     group = NULL;
       
   626     
       
   627     // if item was only partially updated, do not register to snapshot
       
   628     //   --> on next sync item is marked as updated
       
   629     if ( !partiallyUpdated )
       
   630         {
       
   631         // reload group
       
   632         group = static_cast<CContactGroup*>
       
   633             (iContactsDb->ReadContactLC( groupId ));
       
   634         // Inform ChangeFinder of new item
       
   635         TSnapshotItem snapshotItem( groupId );
       
   636         snapshotItem.CreateHashL( *group );
       
   637         iChangeFinder->ItemAddedL( snapshotItem );
       
   638         
       
   639         CleanupStack::PopAndDestroy( group );
       
   640         }
       
   641     
       
   642     
       
   643     
       
   644     TRACE_FUNC_EXIT;
       
   645     return groupId;
       
   646     }
       
   647 
       
   648 // -----------------------------------------------------------------------------
       
   649 // CContactsGrpDataStore::ReplaceGroupL
       
   650 // Replaces existing group on db
       
   651 // -----------------------------------------------------------------------------
       
   652 void CContactsGrpDataStore::ReplaceGroupL( TContactItemId aGroupId, const TDesC& aLabel,
       
   653             const CContactIdArray& aContactArray )
       
   654     {
       
   655     TRACE_FUNC_ENTRY;
       
   656     LOGGER_WRITE_1("aGroupId: %d", aGroupId);
       
   657     LOGGER_WRITE_1("aLabel: %S", &aLabel);
       
   658     TBool partiallyUpdated(EFalse);
       
   659     // check that item exist and is Group-type
       
   660     // The LX suffix means that the lock record of the contact item is left on the cleanup stack.
       
   661     CContactItem* item = iContactsDb->OpenContactLX( aGroupId );
       
   662     CleanupStack::PushL( item );
       
   663     if ( item->Type() != KUidContactGroup )
       
   664         {
       
   665         LOGGER_WRITE("Type was not KUidContactGroup, leaving KErrNotFound");
       
   666         User::Leave( KErrNotFound );
       
   667         }
       
   668     
       
   669     // cast item to CContactGroup type
       
   670     CContactGroup* groupItem = static_cast<CContactGroup*>(item);
       
   671     TContactItemId groupId = groupItem->Id();
       
   672     
       
   673     TBool labelUpdated(EFalse);
       
   674     // Check is group label changed
       
   675     if ( groupItem->HasItemLabelField() )
       
   676         {
       
   677         TPtrC dbLabel = groupItem->GetGroupLabelL();
       
   678         if ( aLabel.Compare( dbLabel ) != 0 )
       
   679             {
       
   680             // didn't match, update label.
       
   681             // Check that new name does not already exist
       
   682             if ( GroupNameExistsL( aLabel ) )
       
   683                 {
       
   684                 LOGGER_WRITE("Name already exists, leave KErrAlreadyExists");
       
   685                 User::Leave( KErrAlreadyExists );
       
   686                 }
       
   687             LOGGER_WRITE("Update label" );
       
   688             groupItem->SetGroupLabelL( aLabel );
       
   689             iContactsDb->CommitContactL( *item );
       
   690             labelUpdated = ETrue;
       
   691             }
       
   692         }
       
   693     TTime lastMod;
       
   694     lastMod.UniversalTime();
       
   695     // Update joined contacts
       
   696     TInt err(KErrNone);
       
   697     // add new items to current group
       
   698     for ( TInt i=0; i<aContactArray.Count(); i++ )
       
   699         {
       
   700         TContactItemId newItem = aContactArray[i];
       
   701         TBool founded = groupItem->ContainsItem( newItem );
       
   702         if ( !founded )
       
   703             {
       
   704             // item does not exist on current group, add it.
       
   705             LOGGER_WRITE_1("Add contact: %d", newItem)
       
   706             TRAP( err, iContactsDb->AddContactToGroupL( newItem, groupId ));
       
   707             if ( err )
       
   708                 {
       
   709                 LOGGER_WRITE_2("Warning: Could not add contact: %d, err: %d", newItem, err);
       
   710                 partiallyUpdated = ETrue;
       
   711                 }
       
   712             else
       
   713                 {
       
   714                 // Update contact timestamp
       
   715                 UpdateContactLastMod( newItem, lastMod );
       
   716                 }
       
   717             }
       
   718         else
       
   719             {
       
   720             LOGGER_WRITE_1("contact( %d ) already exist on group, no need to update", newItem)
       
   721             }
       
   722         }
       
   723     
       
   724     // remove all missing items from group
       
   725     CContactIdArray* oldIdArr = groupItem->ItemsContainedLC();
       
   726     if ( oldIdArr )
       
   727         {
       
   728         for ( TInt i=0; i<oldIdArr->Count(); i++ )
       
   729             {
       
   730             TContactItemId oldItem = (*oldIdArr)[i];
       
   731             TInt err = aContactArray.Find( oldItem );
       
   732             if ( err == KErrNotFound )
       
   733                 {
       
   734                 LOGGER_WRITE_1("Remove contact: %d", oldItem );
       
   735                 // old item was not found from new item list, remove it.
       
   736                 TRAP( err, iContactsDb->RemoveContactFromGroupL(oldItem, groupId));
       
   737                 if ( err )
       
   738                     {
       
   739                     LOGGER_WRITE_2("Warning: Could not remove contact: %d, err: ",oldItem, err );
       
   740                     partiallyUpdated = ETrue;
       
   741                     }
       
   742                 else
       
   743                     {
       
   744                     UpdateContactLastMod( oldItem, lastMod );
       
   745                     }
       
   746                 }
       
   747             // Update all contacts in group if label is changed
       
   748             else if ( labelUpdated )
       
   749                 {
       
   750                 UpdateContactLastMod( oldItem, lastMod );
       
   751                 }
       
   752             }
       
   753         }
       
   754     CleanupStack::PopAndDestroy( oldIdArr );
       
   755     CleanupStack::PopAndDestroy( 2 ); // item, lock object 
       
   756     
       
   757     // if item was only partially updated, do not register to snapshot
       
   758     //   --> on next sync item is marked as updated
       
   759     if ( !partiallyUpdated )
       
   760         {
       
   761         // reload group
       
   762         groupItem = NULL;
       
   763         groupItem = static_cast<CContactGroup*>
       
   764             (iContactsDb->ReadContactLC( groupId ));
       
   765         // Inform ChangeFinder of updated item
       
   766         TSnapshotItem snapshotItem( groupId );
       
   767         snapshotItem.CreateHashL( *groupItem );
       
   768         iChangeFinder->ItemUpdatedL( snapshotItem );
       
   769         
       
   770         CleanupStack::PopAndDestroy( groupItem );
       
   771         }
       
   772     
       
   773     TRACE_FUNC_EXIT;
       
   774     }
       
   775 // -----------------------------------------------------------------------------
       
   776 // CContactsGrpDataStore::DoCloseItem
       
   777 // Closes open item in the data store
       
   778 // -----------------------------------------------------------------------------
       
   779 void CContactsGrpDataStore::DoCloseItem()
       
   780     {
       
   781     TRACE_FUNC_ENTRY;
       
   782     // Reset read buffer 
       
   783     iReaderPosition = KDataBufferNotReady;
       
   784     delete iDataBuffer;
       
   785     iDataBuffer = NULL;
       
   786     
       
   787     // Make sure that we're opened an item
       
   788     if ( iCurrentState != EContactGrpOpening )
       
   789         {
       
   790         LOGGER_WRITE_1( "WARNING: Invalid state %d.", iCurrentState );
       
   791         }
       
   792     // Start to wait for the next operation     
       
   793    iCurrentState = EOpenAndWaiting;
       
   794     
       
   795     TRACE_FUNC_EXIT;   
       
   796     }
       
   797 
       
   798 // -----------------------------------------------------------------------------
       
   799 // CContactsGrpDataStore::DoMoveItemL
       
   800 // Not supported.
       
   801 // -----------------------------------------------------------------------------
       
   802 void CContactsGrpDataStore::DoMoveItemL( TSmlDbItemUid /*aUid*/,
       
   803     TSmlDbItemUid /*aNewParent*/, TRequestStatus& aStatus )
       
   804     {
       
   805     TRACE_FUNC_ENTRY;
       
   806     
       
   807     iCallerStatus = &aStatus;
       
   808     *iCallerStatus = KRequestPending;
       
   809     
       
   810     // Restore state and signal we're done
       
   811     User::RequestComplete( iCallerStatus, KErrNotSupported );
       
   812     
       
   813     TRACE_FUNC_EXIT;
       
   814     }
       
   815 
       
   816 // -----------------------------------------------------------------------------
       
   817 // CContactsGrpDataStore::DoDeleteItemL
       
   818 // Removes item from the message store
       
   819 // -----------------------------------------------------------------------------
       
   820 void CContactsGrpDataStore::DoDeleteItemL( TSmlDbItemUid aUid, TRequestStatus& aStatus )
       
   821     {
       
   822     TRACE_FUNC_ENTRY;
       
   823     LOGGER_WRITE_1( "aUid: %d", aUid );
       
   824     iCallerStatus = &aStatus;
       
   825     *iCallerStatus = KRequestPending;
       
   826     
       
   827     // Check that we're in proper state
       
   828     if ( iCurrentState != EOpenAndWaiting ) 
       
   829         {
       
   830         LOGGER_WRITE_1("CContactsGrpDataStore::DoDeleteItemL, Incorrect state: %d", iCurrentState);
       
   831         }
       
   832     
       
   833     if ( !iContactsDb )
       
   834         {
       
   835         LOGGER_WRITE( "iContactsDb not ready" );
       
   836         User::Leave( KErrNotReady );
       
   837         }
       
   838     
       
   839     // check that item type is ContactGroup
       
   840     CContactItem* item = iContactsDb->ReadContactLC( aUid );
       
   841     if ( item->Type() != KUidContactGroup )
       
   842         {
       
   843         LOGGER_WRITE("Item was not ContactGroup");
       
   844         CleanupStack::PopAndDestroy( item );
       
   845         User::Leave( KErrNotFound );
       
   846         }
       
   847     
       
   848     // Update all contacts in group
       
   849     CContactGroup* groupItem = static_cast<CContactGroup*>(item);
       
   850     CContactIdArray* contactArr = groupItem->ItemsContainedLC();
       
   851     if ( contactArr )
       
   852         {
       
   853         TTime lastMod;
       
   854         lastMod.UniversalTime();
       
   855         for ( TInt i=0; i<contactArr->Count(); i++ )
       
   856             {
       
   857             TContactItemId contactId = (*contactArr)[i];
       
   858             UpdateContactLastMod( contactId, lastMod );
       
   859             }
       
   860         }
       
   861     CleanupStack::PopAndDestroy( contactArr );
       
   862     CleanupStack::PopAndDestroy( item );
       
   863     
       
   864     // delete group
       
   865     iContactsDb->DeleteContactL( aUid );
       
   866     
       
   867     TSnapshotItem snapshotItem( aUid );     
       
   868     iChangeFinder->ItemDeleted( snapshotItem );
       
   869     
       
   870     User::RequestComplete( iCallerStatus, KErrNone );
       
   871         
       
   872     TRACE_FUNC_EXIT;
       
   873     }
       
   874 
       
   875 // -----------------------------------------------------------------------------
       
   876 // CContactsGrpDataStore::DoSoftDeleteItemL
       
   877 // Soft delete isn't supported.
       
   878 // -----------------------------------------------------------------------------
       
   879 void CContactsGrpDataStore::DoSoftDeleteItemL(TSmlDbItemUid /*aUid*/, TRequestStatus& aStatus)
       
   880     {
       
   881     TRACE_FUNC_ENTRY;
       
   882     iCallerStatus = &aStatus;
       
   883     *iCallerStatus = KRequestPending;
       
   884     
       
   885     User::RequestComplete(iCallerStatus, KErrNotSupported); 
       
   886     TRACE_FUNC_EXIT;
       
   887     }
       
   888 
       
   889 // -----------------------------------------------------------------------------
       
   890 // CContactsGrpDataStore::DoDeleteAllItemsL
       
   891 // Deletes all items in the standard folders of bookmark store
       
   892 // -----------------------------------------------------------------------------
       
   893 void CContactsGrpDataStore::DoDeleteAllItemsL( TRequestStatus& aStatus )
       
   894     {
       
   895     TRACE_FUNC_ENTRY;
       
   896 
       
   897     iCallerStatus = &aStatus;
       
   898     *iCallerStatus = KRequestPending;
       
   899     
       
   900     if ( !iContactsDb )
       
   901         {
       
   902         LOGGER_WRITE( "iContactsDb is not opened, Leaving KErrNotReady");
       
   903         User::Leave( KErrNotReady );
       
   904         }
       
   905     
       
   906     CContactIdArray* groups = iContactsDb->GetGroupIdListL();
       
   907     if ( groups )
       
   908         {
       
   909         CleanupStack::PushL( groups );
       
   910         TTime lastMod;
       
   911         lastMod.UniversalTime();
       
   912         
       
   913         // update all contacts in all groups
       
   914         for ( TInt i=0; i<groups->Count(); i++ )
       
   915             {
       
   916             // check that item type is ContactGroup
       
   917             CContactItem* item = iContactsDb->ReadContactLC( (*groups)[i] );
       
   918             
       
   919             // Update all contacts in group
       
   920             CContactGroup* groupItem = static_cast<CContactGroup*>(item);
       
   921             CContactIdArray* contactArr = groupItem->ItemsContainedLC();
       
   922             if ( contactArr )
       
   923                 {
       
   924                 for ( TInt i=0; i<contactArr->Count(); i++ )
       
   925                     {
       
   926                     TContactItemId contactId = (*contactArr)[i];
       
   927                     UpdateContactLastMod( contactId, lastMod );
       
   928                     }
       
   929                 }
       
   930             CleanupStack::PopAndDestroy( contactArr );
       
   931             CleanupStack::PopAndDestroy( item );
       
   932             }
       
   933         
       
   934         // delete all groups
       
   935         iContactsDb->DeleteContactsL( *groups );
       
   936         CleanupStack::PopAndDestroy( groups );
       
   937         }
       
   938     
       
   939     // Reset the whole change finder
       
   940     iChangeFinder->ResetL();
       
   941     
       
   942     User::RequestComplete( iCallerStatus, KErrNone );
       
   943     
       
   944     TRACE_FUNC_EXIT;
       
   945     }
       
   946 
       
   947 // -----------------------------------------------------------------------------
       
   948 // CContactsGrpDataStore::DoHasSyncHistory
       
   949 // This method returns ETrue if Data Store has history information. 
       
   950 // Slow-sync will be used if Data Store does not have history information.
       
   951 // -----------------------------------------------------------------------------
       
   952 TBool CContactsGrpDataStore::DoHasSyncHistory() const
       
   953     {
       
   954     TRACE_FUNC_ENTRY;
       
   955     LOGGER_WRITE_1( "iHasHistory: %d", iHasHistory );
       
   956     TRACE_FUNC_EXIT;  
       
   957     return iHasHistory;
       
   958     }
       
   959 
       
   960 // -----------------------------------------------------------------------------
       
   961 // CContactsGrpDataStore::DoAddedItems
       
   962 // This method returns UIDs of added items. Those items are added after previous
       
   963 // synchronization with current synchronization relationship. 
       
   964 // -----------------------------------------------------------------------------
       
   965 const MSmlDataItemUidSet& CContactsGrpDataStore::DoAddedItems() const
       
   966     {
       
   967     TRACE_FUNC_ENTRY;
       
   968     
       
   969     // Clear new-items array
       
   970     iNewItems->Reset();
       
   971     if ( !iChangeFinder )
       
   972         {
       
   973         LOGGER_WRITE( "WARNING: Not ready, returns empty item list" );
       
   974         return *iNewItems;      
       
   975         }
       
   976     
       
   977     // Search for new items
       
   978     TRAPD( error, iChangeFinder->FindNewItemsL( *iNewItems ) )
       
   979     if ( error != KErrNone )
       
   980         {
       
   981         LOGGER_WRITE_1( "CContactsGrpDataStore::DoAddedItems, iChangeFinder->FindNewItemsL leaved with %d.", error );
       
   982         } 
       
   983     
       
   984     LOGGER_WRITE_1( "New item count: %d.", iNewItems->ItemCount() );    
       
   985     TRACE_FUNC_EXIT;
       
   986     
       
   987     return *iNewItems;  
       
   988     }
       
   989     
       
   990 // -----------------------------------------------------------------------------
       
   991 // CContactsGrpDataStore::DoDeletedItems
       
   992 // Returns ids of items, which are deleted after previous synchronization
       
   993 // -----------------------------------------------------------------------------
       
   994 const MSmlDataItemUidSet& CContactsGrpDataStore::DoDeletedItems() const
       
   995     {
       
   996     TRACE_FUNC_ENTRY;    
       
   997     
       
   998     // Clear deleted-items array
       
   999     iDeletedItems->Reset();
       
  1000     if ( !iChangeFinder )
       
  1001         {
       
  1002         LOGGER_WRITE( "WARNING: Not ready, returns empty item list" );
       
  1003         return *iDeletedItems;      
       
  1004         }
       
  1005     
       
  1006     // Search for deleted items
       
  1007     TRAPD( error, iChangeFinder->FindDeletedItemsL( *iDeletedItems ) );
       
  1008     if ( error != KErrNone )
       
  1009         {
       
  1010         LOGGER_WRITE_1( "CContactsGrpDataStore::DoDeletedItems, iChangeFinder->FindDeletedItemsL leaved with %d.", error );
       
  1011         }
       
  1012     
       
  1013     LOGGER_WRITE_1( "Deleted item count: %d.", iDeletedItems->ItemCount() );
       
  1014     TRACE_FUNC_EXIT;
       
  1015     return *iDeletedItems;
       
  1016     }
       
  1017 
       
  1018 // -----------------------------------------------------------------------------
       
  1019 // CContactsGrpDataStore::DoSoftDeletedItems
       
  1020 // Not directly supported, empty list returned
       
  1021 // -----------------------------------------------------------------------------
       
  1022 const MSmlDataItemUidSet& CContactsGrpDataStore::DoSoftDeletedItems() const
       
  1023     {
       
  1024     TRACE_FUNC;
       
  1025     // Return empty array as a result
       
  1026     return *iEmptyList;
       
  1027     }
       
  1028 
       
  1029 // -----------------------------------------------------------------------------
       
  1030 // CContactsGrpDataStore::DoModifiedItems
       
  1031 // Finds all modified items in the data store
       
  1032 // -----------------------------------------------------------------------------
       
  1033 const MSmlDataItemUidSet& CContactsGrpDataStore::DoModifiedItems() const
       
  1034     {
       
  1035     TRACE_FUNC_ENTRY;
       
  1036     
       
  1037     // Clear updated-items array
       
  1038     iUpdatedItems->Reset();
       
  1039     if ( !iChangeFinder )
       
  1040         {
       
  1041         LOGGER_WRITE( "WARNING: Not ready, returns empty item list" );
       
  1042         return *iUpdatedItems;      
       
  1043         }
       
  1044     
       
  1045     // Search for updated items
       
  1046     TRAPD( error, iChangeFinder->FindChangedItemsL( *iUpdatedItems ) )
       
  1047     if ( error != KErrNone )
       
  1048         {
       
  1049         LOGGER_WRITE_1( "CContactsGrpDataStore::DoModifiedItems, iChangeFinder->FindChangedItemsL leaved with %d.", error );
       
  1050         }
       
  1051     
       
  1052     LOGGER_WRITE_1( "Modified item count: %d.", iUpdatedItems->ItemCount() );
       
  1053     TRACE_FUNC_EXIT;     
       
  1054     return *iUpdatedItems;
       
  1055     }
       
  1056 
       
  1057 // -----------------------------------------------------------------------------
       
  1058 // CContactsGrpDataStore::DoMovedItems
       
  1059 // Finds all moved items in the data store
       
  1060 // -----------------------------------------------------------------------------
       
  1061 const MSmlDataItemUidSet& CContactsGrpDataStore::DoMovedItems() const
       
  1062     {
       
  1063     TRACE_FUNC;
       
  1064     // Moved items are not supported
       
  1065     // Return empty array as a result
       
  1066     return *iEmptyList;
       
  1067     }
       
  1068 
       
  1069 // -----------------------------------------------------------------------------
       
  1070 // CContactsGrpDataStore::DoResetChangeInfoL
       
  1071 // Resets change history in the data store. All content is considered
       
  1072 // new in the data store point of view.
       
  1073 // -----------------------------------------------------------------------------
       
  1074 void CContactsGrpDataStore::DoResetChangeInfoL( TRequestStatus& aStatus )
       
  1075     {
       
  1076     TRACE_FUNC_ENTRY;
       
  1077     
       
  1078     iCallerStatus = &aStatus;
       
  1079     *iCallerStatus = KRequestPending;
       
  1080     
       
  1081     // Check that we're in proper state
       
  1082     if ( iCurrentState != EOpenAndWaiting ) 
       
  1083         {
       
  1084         LOGGER_WRITE_1( "CContactsGrpDataStore::DoResetChangeInfoL, invalid state %d.", iCurrentState );
       
  1085         }   
       
  1086             
       
  1087     // Reset change info in ChangeFinder
       
  1088     iChangeFinder->ResetL();
       
  1089     iHasHistory = EFalse;
       
  1090     
       
  1091     // Signal we're done
       
  1092     User::RequestComplete( iCallerStatus, KErrNone );   
       
  1093         
       
  1094     TRACE_FUNC_EXIT;
       
  1095     }
       
  1096 
       
  1097 // -----------------------------------------------------------------------------
       
  1098 // CContactsGrpDataStore::DoCommitChangeInfoL
       
  1099 // Commits change info. These items are no longer reported, when change
       
  1100 // information is being queried.
       
  1101 // -----------------------------------------------------------------------------
       
  1102 void CContactsGrpDataStore::DoCommitChangeInfoL( TRequestStatus& aStatus,
       
  1103     const MSmlDataItemUidSet& aItems )
       
  1104     {
       
  1105     TRACE_FUNC_ENTRY;
       
  1106     
       
  1107     iCallerStatus = &aStatus;
       
  1108     *iCallerStatus = KRequestPending;
       
  1109     
       
  1110     // Ensure that we're in a proper state
       
  1111     if ( iCurrentState != EOpenAndWaiting ) 
       
  1112         {
       
  1113         LOGGER_WRITE_1( "CContactsGrpDataStore::DoCommitChangeInfoL, invalid state %d.", iCurrentState );
       
  1114         }
       
  1115 
       
  1116     // Notify ChangeFinder
       
  1117     LOGGER_WRITE_1( "CContactsGrpDataStore::DoCommitChangeInfoL, item count %d.", aItems.ItemCount() );
       
  1118     iChangeFinder->CommitChangesL( aItems );
       
  1119     iHasHistory = ETrue;
       
  1120         
       
  1121     // Signal we're done
       
  1122     User::RequestComplete( iCallerStatus, KErrNone );
       
  1123     
       
  1124     TRACE_FUNC_EXIT;
       
  1125     }
       
  1126 
       
  1127 // -----------------------------------------------------------------------------
       
  1128 // CContactsGrpDataStore::DoCommitChangeInfoL
       
  1129 // Commits change info. There is no more nothing to report when change
       
  1130 // information is being queried. 
       
  1131 // -----------------------------------------------------------------------------
       
  1132 void CContactsGrpDataStore::DoCommitChangeInfoL( TRequestStatus& aStatus )
       
  1133     {
       
  1134     TRACE_FUNC_ENTRY;
       
  1135 
       
  1136     iCallerStatus = &aStatus;
       
  1137     *iCallerStatus = KRequestPending;
       
  1138     
       
  1139     // Ensure that we're in a proper state
       
  1140     if ( iCurrentState != EOpenAndWaiting ) 
       
  1141         {
       
  1142         LOGGER_WRITE_1( "CContactsGrpDataStore::DoCommitChangeInfoL, invalid state %d.", iCurrentState );
       
  1143         }
       
  1144     
       
  1145     // Notify ChangeFinder
       
  1146     iChangeFinder->CommitChangesL();
       
  1147     iHasHistory = ETrue;
       
  1148         
       
  1149     // Signal we're done
       
  1150     User::RequestComplete( iCallerStatus, KErrNone );
       
  1151         
       
  1152     TRACE_FUNC_EXIT;
       
  1153     }
       
  1154 
       
  1155 // -----------------------------------------------------------------------------
       
  1156 // CContactsGrpDataStore::RegisterSnapshotL
       
  1157 // Sets Changefinder to compare against current message store content
       
  1158 // -----------------------------------------------------------------------------
       
  1159 void CContactsGrpDataStore::RegisterSnapshotL()
       
  1160     {
       
  1161     TRACE_FUNC_ENTRY;
       
  1162     
       
  1163     CArrayFixSeg<TSnapshotItem>* snapshot = 
       
  1164         new ( ELeave ) CArrayFixSeg<TSnapshotItem>( KSnapshotGranularity );
       
  1165     CleanupStack::PushL( snapshot );
       
  1166     
       
  1167     // Add everything to snapshot
       
  1168     
       
  1169     // GetGroupIdListL returns NULL if there are no groups in the database.
       
  1170     CContactIdArray* groups = iContactsDb->GetGroupIdListL();
       
  1171     if ( groups )
       
  1172         {
       
  1173         TKeyArrayFix key( iKey );
       
  1174         CleanupStack::PushL( groups );
       
  1175         for ( TInt i=0; i<groups->Count(); i++ )
       
  1176             {
       
  1177             CContactItem* item = iContactsDb->ReadContactLC((*groups)[i]);
       
  1178             CContactGroup* groupItem = static_cast<CContactGroup*>(item);
       
  1179             
       
  1180             LOGGER_WRITE_1( "Add group to snatshot, group id: %d",groupItem->Id() );
       
  1181             
       
  1182             TSnapshotItem snapshotItem( groupItem->Id() );
       
  1183             snapshotItem.CreateHashL( *groupItem );
       
  1184             
       
  1185             snapshot->InsertIsqL( snapshotItem, key );
       
  1186             
       
  1187             CleanupStack::PopAndDestroy( item );
       
  1188             }
       
  1189         CleanupStack::PopAndDestroy( groups );
       
  1190         }
       
  1191     
       
  1192     // Set new snapshot to compare against
       
  1193     iChangeFinder->SetNewSnapshot( snapshot );
       
  1194     
       
  1195     // Changefinder takes ownership of the snapshot
       
  1196     CleanupStack::Pop( snapshot );
       
  1197     
       
  1198     TRACE_FUNC_EXIT;
       
  1199     }
       
  1200 
       
  1201 // -----------------------------------------------------------------------------
       
  1202 // CContactsGrpDataStore::AssignString
       
  1203 // Assigns data from one descriptor into another, truncates if too long 
       
  1204 // -----------------------------------------------------------------------------
       
  1205 void CContactsGrpDataStore::AssignString( TDes8& aDestination, const TDesC8& aSource )
       
  1206     {
       
  1207     TInt targetLength = aSource.Length();
       
  1208     if ( aDestination.MaxLength() < targetLength )
       
  1209         {
       
  1210         targetLength = aDestination.MaxLength();
       
  1211         }
       
  1212         
       
  1213     aDestination.Copy( aSource.Ptr(), targetLength );
       
  1214     }
       
  1215 
       
  1216 // -----------------------------------------------------------------------------
       
  1217 // CContactsGrpDataStore::UpdateContactLastMod
       
  1218 // Updates contact item last modified time. Contact sync will see item as changed one.
       
  1219 // -----------------------------------------------------------------------------
       
  1220 void CContactsGrpDataStore::UpdateContactLastMod( TContactItemId aContactId,
       
  1221         const TTime& aLastModified )
       
  1222     {
       
  1223     // Ignore errors.
       
  1224     // Cannot update timestamp if contact is already open. However modified time
       
  1225     // is most likely still updated by UI.
       
  1226     TRAP_IGNORE(
       
  1227         // OpenContactLX() places the edit lock on the cleanup stack
       
  1228         CContactItem* contact = iContactsDb->OpenContactLX( aContactId );
       
  1229         CleanupStack::PushL( contact );
       
  1230         contact->SetLastModified( aLastModified );
       
  1231         iContactsDb->CommitContactL( *contact );
       
  1232         CleanupStack::PopAndDestroy( contact );
       
  1233         CleanupStack::PopAndDestroy( 1 ); // lock object
       
  1234         );
       
  1235     }
       
  1236 
       
  1237 // -----------------------------------------------------------------------------
       
  1238 // CContactsGrpDataStore::GroupNameExistsL
       
  1239 // Checks does group name already exists.
       
  1240 // -----------------------------------------------------------------------------
       
  1241 TBool CContactsGrpDataStore::GroupNameExistsL( const TDesC& aLabel )
       
  1242     {
       
  1243     TBool duplicateFound( EFalse );
       
  1244     // GetGroupIdListL returns NULL if there are no groups in the database.
       
  1245     CContactIdArray* groups = iContactsDb->GetGroupIdListL();
       
  1246     if ( groups )
       
  1247         {
       
  1248         CleanupStack::PushL( groups );
       
  1249         for ( TInt i=0; i<groups->Count() && !duplicateFound; i++ )
       
  1250             {
       
  1251             CContactItem* item = iContactsDb->ReadContactLC((*groups)[i]);
       
  1252             CContactGroup* groupItem = static_cast<CContactGroup*>(item);
       
  1253             
       
  1254             if ( groupItem->HasItemLabelField() )
       
  1255                 {
       
  1256                 TPtrC label = groupItem->GetGroupLabelL();
       
  1257                 if ( aLabel.Compare( label ) == 0 )
       
  1258                     {
       
  1259                     duplicateFound = ETrue;
       
  1260                     }
       
  1261                 }
       
  1262             CleanupStack::PopAndDestroy( item );
       
  1263             }
       
  1264         CleanupStack::PopAndDestroy( groups );
       
  1265         }
       
  1266     
       
  1267     return duplicateFound;
       
  1268     }