meetingui/meetingrequestutils/src/CMRUtilsCalDbMgr.cpp
changeset 0 f979ecb2b13e
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     1 /*
       
     2 * Copyright (c) 2005 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: Implementation for meeting request utils calendar    
       
    15 *              database manager
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // ----------------------------------------------------------------------------
       
    21 // INCLUDE FILES
       
    22 // ----------------------------------------------------------------------------
       
    23 //
       
    24 #include "CMRUtilsCalDbMgr.h"
       
    25 #include "CMRUtilsCalDbNormal.h"
       
    26 #include "CMRUtilsCalDbTombs.h"
       
    27 #include "CMRUtilsCmdIterationAO.h"
       
    28 #include "CMRUtilsGraveyardCleaner.h"
       
    29 #include "MREntryConsultant.h"
       
    30 #include "MRHelpers.h"
       
    31 #include "ICalUILog.h"
       
    32 #include "CMRUtilsInternal.h"
       
    33 #include <ct/RCPointerArray.h>
       
    34 #include <CalSession.h>
       
    35 #include <CalEntryView.h>
       
    36 #include <CalInstance.h>
       
    37 #include <CalInstanceView.h>
       
    38 #include <CalEntry.h>
       
    39 #include <CalCommon.h>
       
    40 #include <CalUser.h>
       
    41 #include <CalenInterimUtils2.h>
       
    42 
       
    43 // CONSTANTS
       
    44 /// Unnamed namespace for local definitions
       
    45 namespace {
       
    46 
       
    47 const TInt KUidListGranularity = 10;
       
    48 
       
    49 enum TPanicCode
       
    50     {
       
    51     EPanicIllegalFetchParams = 1,
       
    52     EPanicAccessedWhenUnavailable,
       
    53     EPanicAsyncOpAlreadyExists,
       
    54     EPanicIllegalEntryStatus,
       
    55     EPanicIllegalResurrect,
       
    56     EPanicUnexpectedUidValue
       
    57     };
       
    58 
       
    59 _LIT( KPanicMsg, "CMRUtilsCalDbMgr" );
       
    60 
       
    61 void Panic( TPanicCode aReason )
       
    62     {
       
    63     User::Panic( KPanicMsg, aReason );
       
    64     }
       
    65     
       
    66 }  // namespace
       
    67 
       
    68 // ----------------------------------------------------------------------------
       
    69 // MEMBER FUNCTIONS
       
    70 // ----------------------------------------------------------------------------
       
    71 //
       
    72 
       
    73 // ----------------------------------------------------------------------------
       
    74 // CMRUtilsCalDbMgr::NewL
       
    75 // ----------------------------------------------------------------------------
       
    76 //
       
    77 CMRUtilsCalDbMgr* CMRUtilsCalDbMgr::NewL(
       
    78     CCalSession& aCalSession,
       
    79     MMRUtilsObserver& aObserver )
       
    80 	{
       
    81 	CMRUtilsCalDbMgr* self = new( ELeave ) CMRUtilsCalDbMgr( aCalSession,
       
    82 	                                                         aObserver );
       
    83 	CleanupStack::PushL( self );
       
    84 	self->ConstructL();
       
    85 	CleanupStack::Pop();
       
    86 	return self;
       
    87 	}
       
    88 
       
    89 // ----------------------------------------------------------------------------
       
    90 // CMRUtilsCalDbMgr::CMRUtilsCalDbMgr
       
    91 //
       
    92 // Constructor.
       
    93 // ----------------------------------------------------------------------------
       
    94 //
       
    95 CMRUtilsCalDbMgr::CMRUtilsCalDbMgr(
       
    96     CCalSession& aCalSession,
       
    97     MMRUtilsObserver& aObserver )
       
    98     : iCurrentAsyncOp( CMRUtils::ENoOperation ),
       
    99       iCalSession( aCalSession ),
       
   100       iObserver( aObserver )    
       
   101     {    
       
   102     }
       
   103     
       
   104 // ----------------------------------------------------------------------------
       
   105 // CMRUtilsCalDbMgr::~CMRUtilsCalDbMgr
       
   106 //
       
   107 // Destructor.
       
   108 // ----------------------------------------------------------------------------
       
   109 //        
       
   110 CMRUtilsCalDbMgr::~CMRUtilsCalDbMgr()
       
   111     {
       
   112     delete iGraveyardCleaner;
       
   113     delete iCmdIterator;
       
   114     delete iNormalDb;
       
   115     delete iTombsDb;
       
   116     }
       
   117     
       
   118 // ----------------------------------------------------------------------------
       
   119 // CMRUtilsCalDbMgr::ConstructL
       
   120 // ----------------------------------------------------------------------------
       
   121 //    
       
   122 void CMRUtilsCalDbMgr::ConstructL()
       
   123     {
       
   124     iNormalDb = CMRUtilsCalDbNormal::NewL( iCalSession, *this, *this );
       
   125     iTombsDb = CMRUtilsCalDbTombs::NewL( *this, *this );    
       
   126     iCmdIterator = CMRUtilsCmdIterationAO::NewL( *this );
       
   127     }
       
   128 
       
   129 // ----------------------------------------------------------------------------
       
   130 // CMRUtilsCalDbMgr::HandleCalDbStatus
       
   131 // ----------------------------------------------------------------------------
       
   132 //    
       
   133 void CMRUtilsCalDbMgr::HandleCalDbStatus(
       
   134     const CMRUtilsCalDbBase* /*aNotifier*/,
       
   135     MMRUtilsCalDbObserver::TDbStatus aStatus )
       
   136     {
       
   137     // If there is any change in db status, we must stop cleaning:
       
   138     delete iGraveyardCleaner;
       
   139     iGraveyardCleaner = NULL;
       
   140     
       
   141     if ( aStatus == EReseting )
       
   142         { // reset db is ongoing, engine becomes unavailable
       
   143         iObserver.HandleCalEngStatus( MMRUtilsObserver::ENotReady );
       
   144         }
       
   145     else if ( iNormalDb->DbStatus() == MMRUtilsCalDbObserver::EFinishedOk &&
       
   146               iTombsDb->DbStatus() == MMRUtilsCalDbObserver::EFinishedOk )
       
   147         {
       
   148         iObserver.HandleCalEngStatus( MMRUtilsObserver::EAvailable );        
       
   149         // Both databases are available so we can start idle cleanup
       
   150         // We can ignore the error if it fails, try again next time
       
   151         TRAP_IGNORE(
       
   152             iGraveyardCleaner =
       
   153                 CMRUtilsGraveyardCleaner::NewL( *iNormalDb, *iTombsDb );
       
   154             iGraveyardCleaner->StartIdleCleanupL( Time::NullTTime() );
       
   155             )
       
   156         }
       
   157     else if ( iNormalDb->DbStatus() == MMRUtilsCalDbObserver::EFinishedOk &&
       
   158               iTombsDb->DbStatus() == MMRUtilsCalDbObserver::EFinishedError )
       
   159         {
       
   160         iObserver.HandleCalEngStatus(
       
   161             MMRUtilsObserver::EAvailableWithoutTombs );
       
   162         }
       
   163     else if ( iNormalDb->DbStatus() == MMRUtilsCalDbObserver::EFinishedError )
       
   164         {
       
   165         iObserver.HandleCalEngStatus( MMRUtilsObserver::ENotAvailable );
       
   166         }
       
   167         
       
   168     // In other cases either db is not yet finished        
       
   169     }
       
   170     
       
   171 // ----------------------------------------------------------------------------
       
   172 // CMRUtilsCalDbMgr::Progress
       
   173 // ----------------------------------------------------------------------------
       
   174 //
       
   175 void CMRUtilsCalDbMgr::Progress( TInt /*aPercentageCompleted*/ )
       
   176     {
       
   177     // Not interested in progress currently
       
   178     }
       
   179     
       
   180 // ----------------------------------------------------------------------------
       
   181 // CMRUtilsCalDbMgr::NotifyProgress
       
   182 // ----------------------------------------------------------------------------
       
   183 //
       
   184 TBool CMRUtilsCalDbMgr::NotifyProgress()
       
   185     {
       
   186     // Not interested in progress currently
       
   187     return EFalse;
       
   188     }
       
   189 
       
   190 // ----------------------------------------------------------------------------
       
   191 // CMRUtilsCalDbMgr::Completed
       
   192 // ----------------------------------------------------------------------------
       
   193 //
       
   194 void CMRUtilsCalDbMgr::Completed( TInt aError )
       
   195     {
       
   196     iObserver.HandleOperation( iCurrentAsyncOp, 100, aError );
       
   197     iCurrentAsyncOp = CMRUtils::ENoOperation;
       
   198     }
       
   199 
       
   200 // ----------------------------------------------------------------------------
       
   201 // CMRUtilsCalDbMgr::NormalDbEntryView
       
   202 // ----------------------------------------------------------------------------
       
   203 //
       
   204 CCalEntryView* CMRUtilsCalDbMgr::NormalDbEntryView()
       
   205     { // NormalDbEntryView will only be called if engine is available
       
   206     return iNormalDb->EntryView();
       
   207     }
       
   208      
       
   209 // ----------------------------------------------------------------------------
       
   210 // CMRUtilsCalDbMgr::NormalDbInstanceView
       
   211 // ----------------------------------------------------------------------------
       
   212 //
       
   213 CCalInstanceView* CMRUtilsCalDbMgr::NormalDbInstanceView()
       
   214     { // NormalDbInstanceView will only be called if engine is available
       
   215     return iNormalDb->InstanceView();
       
   216     }
       
   217 
       
   218 // ----------------------------------------------------------------------------
       
   219 // CMRUtilsCalDbMgr::FetchEntriesL
       
   220 // ----------------------------------------------------------------------------
       
   221 //
       
   222 void CMRUtilsCalDbMgr::FetchEntriesL(
       
   223     RPointerArray<CCalEntry>& aCalEntryArray,
       
   224     const CalCommon::TCalTimeRange& aTimeRange )
       
   225     {
       
   226     __ASSERT_DEBUG( aCalEntryArray.Count() == 0,
       
   227                     Panic( EPanicIllegalFetchParams ) );
       
   228     aCalEntryArray.ResetAndDestroy();
       
   229     // caller definitely wants to get full copies -> ETrue as 3rd argument:
       
   230     iNormalDb->FetchWithRangeL( aCalEntryArray,
       
   231                                 aTimeRange,
       
   232                                 ETrue );    
       
   233     }
       
   234 
       
   235 // ----------------------------------------------------------------------------
       
   236 // CMRUtilsCalDbMgr::FetchEntryL
       
   237 // ----------------------------------------------------------------------------
       
   238 //
       
   239 CCalEntry* CMRUtilsCalDbMgr::FetchEntryL(
       
   240     const TDesC8& aUid,
       
   241     const TCalTime& aRecurrenceId )
       
   242     {
       
   243     __ASSERT_DEBUG( aUid.Length() > 0,
       
   244                     Panic( EPanicIllegalFetchParams ) );
       
   245     
       
   246     RCPointerArray<CCalEntry> tmpFetchArray;
       
   247     CleanupClosePushL( tmpFetchArray ); 
       
   248     
       
   249     CCalEntry* retVal = NULL;
       
   250 
       
   251     TInt index( -1 );
       
   252     if ( EntryExistsInDbL( aUid,
       
   253                            aRecurrenceId,
       
   254                            *iNormalDb,
       
   255                            tmpFetchArray,
       
   256                            index ) )
       
   257         {        
       
   258         retVal = tmpFetchArray[index];        
       
   259         tmpFetchArray.Remove( index ); // ownership transferred to retVal
       
   260         }        
       
   261         
       
   262     CleanupStack::PopAndDestroy(); // tmpFetchArray
       
   263     return retVal;
       
   264     }        
       
   265 
       
   266 // ----------------------------------------------------------------------------
       
   267 // CMRUtilsCalDbMgr::StoreEntryL
       
   268 // ----------------------------------------------------------------------------
       
   269 //          
       
   270 TInt CMRUtilsCalDbMgr::StoreEntryL(
       
   271     CCalEntry& aCalEntry,
       
   272     TBool aToNormalDb )
       
   273     {
       
   274     TInt retVal( KErrNone );   
       
   275     
       
   276     CMRUtilsCalDbBase* dbToStore = aToNormalDb ? iNormalDb : iTombsDb;    
       
   277     CCalenInterimUtils2::StoreL( *( dbToStore->EntryView() ),
       
   278                                  aCalEntry,
       
   279                                  ETrue );
       
   280     
       
   281     return retVal;
       
   282     }        
       
   283 
       
   284 // ----------------------------------------------------------------------------
       
   285 // CMRUtilsCalDbMgr::UpdateEntryL
       
   286 // ----------------------------------------------------------------------------
       
   287 //          
       
   288 TInt CMRUtilsCalDbMgr::UpdateEntryL( const CCalEntry& aCalEntry )
       
   289     {
       
   290     RPointerArray<CCalEntry> calEntryTmpArray( 1 ); // entry not own
       
   291     CleanupClosePushL( calEntryTmpArray ); 
       
   292     calEntryTmpArray.AppendL( &aCalEntry );
       
   293     TInt numSuccessfulEntry( 0 );
       
   294     // entry view surely exists when status is 'available':
       
   295     iNormalDb->EntryView()->UpdateL( calEntryTmpArray, numSuccessfulEntry );
       
   296     TInt retVal( numSuccessfulEntry == 1 ? KErrNone : KErrGeneral );
       
   297     CleanupStack::PopAndDestroy(); // calEntryTmpArray, only close array
       
   298     return retVal;    
       
   299     }        
       
   300 
       
   301 // ----------------------------------------------------------------------------
       
   302 // CMRUtilsCalDbMgr::DeleteEntryL
       
   303 // ----------------------------------------------------------------------------
       
   304 //          
       
   305 TInt CMRUtilsCalDbMgr::DeleteEntryL( const TDesC8& aUid )
       
   306     {  
       
   307     CDesC8ArrayFlat* uidArray = new( ELeave ) CDesC8ArrayFlat( 1 );
       
   308     CleanupStack::PushL( uidArray );
       
   309     uidArray->AppendL( aUid );
       
   310     // entry view surely exists when status is 'available':
       
   311     iNormalDb->EntryView()->DeleteL( *uidArray );
       
   312     CleanupStack::PopAndDestroy( uidArray );
       
   313     return KErrNone;    
       
   314     }        
       
   315 
       
   316 // ----------------------------------------------------------------------------
       
   317 // CMRUtilsCalDbMgr::DeleteEntryL
       
   318 // ----------------------------------------------------------------------------
       
   319 //          
       
   320 TInt CMRUtilsCalDbMgr::DeleteEntryL( const TCalLocalUid& aLocalUid )
       
   321     {
       
   322     RArray<TCalLocalUid> localUidArray( 1 );
       
   323     CleanupClosePushL( localUidArray ); 
       
   324     localUidArray.AppendL( aLocalUid );
       
   325     TInt numSuccessfulEntry( 0 );
       
   326     iNormalDb->EntryView()->DeleteL( localUidArray, numSuccessfulEntry );
       
   327     TInt retVal( numSuccessfulEntry == 1 ? KErrNone : KErrGeneral );
       
   328     CleanupStack::PopAndDestroy(); // localUidArray
       
   329     return retVal;
       
   330     }
       
   331      
       
   332 // ----------------------------------------------------------------------------
       
   333 // CMRUtilsCalDbMgr::ResetTombsFileL
       
   334 // ----------------------------------------------------------------------------
       
   335 //          
       
   336 void CMRUtilsCalDbMgr::ResetTombsFileL()
       
   337     {
       
   338     iTombsDb->ResetDbL();
       
   339     }
       
   340     
       
   341 // ----------------------------------------------------------------------------
       
   342 // CMRUtilsCalDbMgr::DeleteTombstonesL
       
   343 // ----------------------------------------------------------------------------
       
   344 //          
       
   345 void CMRUtilsCalDbMgr::DeleteTombstonesL(
       
   346     const CalCommon::TCalTimeRange& aCalTimeRange )
       
   347     {
       
   348     __ASSERT_DEBUG( iCurrentAsyncOp == CMRUtils::ENoOperation,
       
   349                     Panic( EPanicAsyncOpAlreadyExists ) );
       
   350     iTombsDb->EntryView()->DeleteL( aCalTimeRange,
       
   351                                     CalCommon::EIncludeAppts,
       
   352                                     *this );
       
   353     iCurrentAsyncOp = CMRUtilsInternal::EDeleteTombstones;
       
   354     }
       
   355 
       
   356 // ----------------------------------------------------------------------------
       
   357 // CMRUtilsCalDbMgr::StoreEntryCondL
       
   358 // aResurrect can only be ETrue if aCheckOnly is EFalse, i.e. when user is
       
   359 // really trying to store something.
       
   360 // ----------------------------------------------------------------------------
       
   361 //          
       
   362 MMRUtilsTombsExt::TMRUtilsDbResult CMRUtilsCalDbMgr::StoreEntryCondL(
       
   363     CCalEntry& aCalEntry,
       
   364     TBool aResurrect,
       
   365     TBool aCheckOnly )
       
   366     {    
       
   367     RCPointerArray<CCalEntry> tmpFetchArray;
       
   368     CleanupClosePushL( tmpFetchArray );
       
   369         
       
   370     MMRUtilsTombsExt::TMRUtilsDbResult entryStatus(
       
   371         MMRUtilsTombsExt::EUndefined );
       
   372     TInt index( -1 );
       
   373     
       
   374     // 1. Normal db part, if entry is found in there then tombstones aren't
       
   375     //    checked at all:
       
   376     
       
   377     if ( EntryExistsInDbL( aCalEntry, *iNormalDb, tmpFetchArray, index ) )
       
   378         { // Entry exists in normal db
       
   379         entryStatus = EvaluateExistingEntryL( aCalEntry,
       
   380                                               *( tmpFetchArray[index] ) );
       
   381         if ( entryStatus == MMRUtilsTombsExt::ECheckedValidUpdate &&
       
   382              !aCheckOnly ) 
       
   383             {
       
   384             StoreEntryL( aCalEntry );
       
   385             entryStatus = MMRUtilsTombsExt::EStoredUpdate;
       
   386             }
       
   387         else if ( entryStatus == MMRUtilsTombsExt::EErrorCancelled &&
       
   388                   aResurrect ) 
       
   389             {
       
   390             __ASSERT_DEBUG( !aCheckOnly, Panic( EPanicIllegalResurrect ) );
       
   391             StoreEntryL( aCalEntry );
       
   392             entryStatus = MMRUtilsTombsExt::EResurrectedCancelled;
       
   393             }            
       
   394         // entry can't be new if it exists in the db already:            
       
   395         __ASSERT_DEBUG( entryStatus != MMRUtilsTombsExt::ECheckedValidNew,
       
   396                         Panic( EPanicIllegalEntryStatus) );                        
       
   397         }
       
   398         
       
   399     // 2. Tombstone db part (omitted if tombs db unavailable):
       
   400         
       
   401     else if ( iTombsDb->DbStatus() == MMRUtilsCalDbObserver::EFinishedOk &&
       
   402               EntryExistsInDbL( aCalEntry, *iTombsDb, tmpFetchArray, index ) )
       
   403         { // Entry has been deleted and is a tombstone now
       
   404         entryStatus = EvaluateExistingEntryL( aCalEntry,
       
   405                                               *( tmpFetchArray[index] ) );
       
   406                                               
       
   407                                               
       
   408         if ( entryStatus == MMRUtilsTombsExt::ECheckedValidUpdate &&
       
   409              !aCheckOnly )
       
   410             { // Older entry exists in tombstone db, our policy is that
       
   411               // updates are still accepted
       
   412             if ( MREntryConsultant::IsModifyingEntryL( aCalEntry ) &&
       
   413                  !OriginatingExistInDbL( aCalEntry ) )
       
   414                 { // originating not found in normal db, so modifying entry
       
   415                   // is "illegal", cannot be saved
       
   416                 entryStatus = MMRUtilsTombsExt::EErrorRecurrence;
       
   417                 }
       
   418             else
       
   419                 {                
       
   420                 StoreEntryL( aCalEntry );
       
   421                 entryStatus = MMRUtilsTombsExt::EStoredUpdate;
       
   422                 // Try to delete this particular tombstone, any further
       
   423                 // tombstone cleanup is taken care by a separate class:         
       
   424                 TRAP_IGNORE( iTombsDb->EntryView()->DeleteL( aCalEntry ) );
       
   425                 }
       
   426             }
       
   427         else if ( entryStatus == MMRUtilsTombsExt::EErrorIdenticalExists )
       
   428             { // Identical entry exists in tombstone db
       
   429             if ( aResurrect )
       
   430                 {
       
   431                 __ASSERT_DEBUG( !aCheckOnly, Panic( EPanicIllegalResurrect ) );
       
   432                 if ( MREntryConsultant::IsModifyingEntryL( aCalEntry ) &&
       
   433                      !OriginatingExistInDbL( aCalEntry ) )
       
   434                     { // originating not found in normal db, so modifying entry
       
   435                       // is "illegal", cannot be resurrected
       
   436                     entryStatus = MMRUtilsTombsExt::EErrorRecurrence;
       
   437                     }
       
   438                 else
       
   439                     {                    
       
   440                     StoreEntryL( aCalEntry );
       
   441                     entryStatus = MMRUtilsTombsExt::EResurrectedDeleted;                                    
       
   442                     // Try to delete this particular tombstone, any further
       
   443                     // tombstone cleanup is taken care by a separate class:         
       
   444                     TRAP_IGNORE( iTombsDb->EntryView()->DeleteL( aCalEntry ) );
       
   445                     }
       
   446                 }
       
   447             else
       
   448                 {                                
       
   449                 entryStatus = MMRUtilsTombsExt::EErrorHasBeenDeleted;
       
   450                 }
       
   451             }
       
   452         // entry can't be new if it exists in the db already:            
       
   453         __ASSERT_DEBUG( entryStatus != MMRUtilsTombsExt::ECheckedValidNew,
       
   454                         Panic( EPanicIllegalEntryStatus) );                        
       
   455         }
       
   456         
       
   457     // 3. New entry in this phone:
       
   458         
       
   459     else
       
   460         { // Completely new entry (or tombstone has disappeared)
       
   461         entryStatus = EvaluateNewEntryL( aCalEntry );
       
   462         if ( entryStatus == MMRUtilsTombsExt::ECheckedValidNew && !aCheckOnly )
       
   463             {
       
   464             StoreEntryL( aCalEntry );
       
   465             entryStatus = MMRUtilsTombsExt::EStoredNew;
       
   466             }
       
   467         
       
   468         // entry can't be update if doesn't exist in the db already:        
       
   469         __ASSERT_DEBUG( entryStatus != MMRUtilsTombsExt::ECheckedValidUpdate,
       
   470                         Panic( EPanicIllegalEntryStatus) );         
       
   471         }
       
   472         
       
   473     CleanupStack::PopAndDestroy(); // tmpFetchArray
       
   474     return entryStatus;        
       
   475     }
       
   476 
       
   477 // ----------------------------------------------------------------------------
       
   478 // CMRUtilsCalDbMgr::DeleteEntryCondL
       
   479 // ----------------------------------------------------------------------------
       
   480 //          
       
   481 void CMRUtilsCalDbMgr::DeleteEntryCondL( const TDesC8& aUid )
       
   482     {
       
   483     RCPointerArray<CCalEntry> tmpFetchArray;
       
   484     CleanupClosePushL( tmpFetchArray );
       
   485     
       
   486     // 1. Delete all found entries from normal db:
       
   487     
       
   488     iNormalDb->EntryView()->FetchL( aUid, tmpFetchArray );
       
   489     DeleteEntryL( aUid );
       
   490 
       
   491     // 2. Add them to tombstone db, if this fails then no tombstone gets
       
   492     // created, but that isn't a major problem:
       
   493             
       
   494     if ( iTombsDb->DbStatus() == MMRUtilsCalDbObserver::EFinishedError )
       
   495         { // if tombstone db isn't available then we omit it silently          
       
   496         return;
       
   497         }
       
   498             
       
   499     TInt count( tmpFetchArray.Count() );
       
   500     for ( TInt i( 0 ); i < count; ++i )
       
   501         {
       
   502 // TODO: currently child entry uid cannot be read anymore after it has been
       
   503 // deleted from the db, this might be a bug in CalInterimApi. Check later
       
   504 // if it works, if doesn't we could e.g. make a copy of each entry before
       
   505 // deleting it and delete and store one at a time, parent as the last one.
       
   506 // See also DeleteEntryCondL( const CCalEntry& aCalEntry ) variant below.       
       
   507         CCalEntry* tombstone = MRHelpers::CopyEntryLC( *( tmpFetchArray[i] ),
       
   508                                                 tmpFetchArray[i]->MethodL(),
       
   509                                                 MRHelpers::ECopySkeleton );
       
   510         // store to iTombsDb, parent will be added first (it has index 0):
       
   511         // don't care if creating a tombstone would fail
       
   512         TRAP_IGNORE( StoreEntryL( *tombstone, EFalse ) );
       
   513         CleanupStack::PopAndDestroy( tombstone );        
       
   514         }
       
   515     
       
   516     CleanupStack::PopAndDestroy(); // tmpFetchArray
       
   517     }
       
   518 
       
   519 // ----------------------------------------------------------------------------
       
   520 // CMRUtilsCalDbMgr::DeleteEntryCondL
       
   521 // ----------------------------------------------------------------------------
       
   522 //          
       
   523 void CMRUtilsCalDbMgr::DeleteEntryCondL( const TCalLocalUid& aLocalUid )
       
   524     {
       
   525     CCalEntry* entry = iNormalDb->EntryView()->FetchL( aLocalUid );
       
   526     if ( entry )
       
   527         {
       
   528         CleanupStack::PushL( entry );
       
   529         DeleteEntryCondL( *entry );
       
   530         CleanupStack::PopAndDestroy( entry );
       
   531         }
       
   532     }
       
   533 
       
   534 // ----------------------------------------------------------------------------
       
   535 // CMRUtilsCalDbMgr::DeleteEntryCondL
       
   536 // ----------------------------------------------------------------------------
       
   537 //          
       
   538 void CMRUtilsCalDbMgr::DeleteEntryCondL( const CCalEntry& aCalEntry )
       
   539     {        
       
   540     if ( MREntryConsultant::IsModifyingEntryL( aCalEntry ) )
       
   541         { // Modifying entry
       
   542         
       
   543         // 1. Delete entry from normal db:
       
   544 
       
   545 // TODO: see above the problem of storing children to tombs db        
       
   546 
       
   547         iNormalDb->EntryView()->DeleteL( aCalEntry );
       
   548         
       
   549         // 2. Add it to tombstone db, if this fails then no tombstone gets
       
   550         // created, but that isn't a major problem:
       
   551         
       
   552         if ( iTombsDb->DbStatus() == MMRUtilsCalDbObserver::EFinishedError )
       
   553             { // if tombstone db isn't available then we omit it silently          
       
   554             return;
       
   555             }
       
   556         
       
   557         // We must ensure that originating entry exists in tombstone db,
       
   558         // but if it exists already it mustn't be stored again since that
       
   559         // would automatically clean up any related modifying entries:        
       
   560         TInt dummyIndex( -1 ); // unused but required
       
   561         RCPointerArray<CCalEntry> tmpFetchArray;
       
   562         CleanupClosePushL( tmpFetchArray );        
       
   563         TBool origExistsInTombsDb = EntryExistsInDbL( aCalEntry.UidL(),
       
   564                                                       TCalTime(),
       
   565                                                       *iTombsDb,
       
   566                                                       tmpFetchArray,
       
   567                                                       dummyIndex );
       
   568         tmpFetchArray.ResetAndDestroy();
       
   569         if ( !origExistsInTombsDb )
       
   570             { // Copy originating entry from normal to tombs db:
       
   571             iNormalDb->EntryView()->FetchL( aCalEntry.UidL(), tmpFetchArray );          
       
   572             CCalEntry* orig = MRHelpers::CopyEntryLC( *( tmpFetchArray[0] ),
       
   573                                                 tmpFetchArray[0]->MethodL(),
       
   574                                                 MRHelpers::ECopySkeleton );
       
   575             tmpFetchArray.ResetAndDestroy();
       
   576             // to iTombsDb, don't care if creating a tombstone would fail
       
   577             TRAP_IGNORE( StoreEntryL( *orig, EFalse ) );
       
   578             CleanupStack::PopAndDestroy( orig );
       
   579             }            
       
   580         CleanupStack::PopAndDestroy(); // tmpFetchArray
       
   581             
       
   582         // Now store the modifying entry to tombstone db:            
       
   583         CCalEntry* modif = MRHelpers::CopyEntryLC( aCalEntry,
       
   584                                                    aCalEntry.MethodL(),
       
   585                                                    MRHelpers::ECopySkeleton );
       
   586         // to iTombsDb, don't care if creating a tombstone would fail           
       
   587         TRAP_IGNORE( StoreEntryL( *modif, EFalse ) );
       
   588         CleanupStack::PopAndDestroy( modif );                                
       
   589         }
       
   590         
       
   591     else
       
   592         { // Originating entry, this is the same case as deleting with GUID:
       
   593         DeleteEntryCondL( aCalEntry.UidL() );
       
   594         }            
       
   595     }
       
   596 
       
   597 // ----------------------------------------------------------------------------
       
   598 // CMRUtilsCalDbMgr::DeleteEntryCondL
       
   599 // ----------------------------------------------------------------------------
       
   600 //          
       
   601 void CMRUtilsCalDbMgr::DeleteEntryCondL(
       
   602     const CalCommon::TCalTimeRange& aCalTimeRange )
       
   603     {
       
   604     __ASSERT_DEBUG( iCurrentAsyncOp == CMRUtils::ENoOperation,
       
   605                     Panic( EPanicAsyncOpAlreadyExists ) );    
       
   606     
       
   607     RCPointerArray<CCalEntry> tmpFetchArray;
       
   608     CleanupClosePushL( tmpFetchArray );       
       
   609     // skeleton copies are enough -> set 3rd argument to EFalse:
       
   610     iNormalDb->FetchWithRangeL( tmpFetchArray, aCalTimeRange, EFalse );
       
   611     iCmdIterator->StartCmdIterationL( tmpFetchArray, CMRUtils::EDeleteEntries );
       
   612     iCurrentAsyncOp = CMRUtils::EDeleteEntries;                                                 
       
   613     tmpFetchArray.Reset(); // ownership of entries was transferred
       
   614     CleanupStack::PopAndDestroy(); // tmpFetchArray
       
   615     }
       
   616 
       
   617 // ----------------------------------------------------------------------------
       
   618 // CMRUtilsCalDbMgr::EntryExistsInDbL
       
   619 // ----------------------------------------------------------------------------
       
   620 //   
       
   621 TBool CMRUtilsCalDbMgr::EntryExistsInDbL(
       
   622     const TDesC8& aUid,
       
   623     const TCalTime& aRecurrenceId,
       
   624     const CMRUtilsCalDbBase& aDb,
       
   625     RPointerArray<CCalEntry>& aCalEntryArray,
       
   626     TInt& aIndex ) const
       
   627     {
       
   628     TBool retVal( EFalse );
       
   629     aIndex = -1;
       
   630     
       
   631     aDb.EntryView()->FetchL( aUid, aCalEntryArray );
       
   632     TInt count( aCalEntryArray.Count() );
       
   633     for ( TInt i( 0 ); i < count; ++i )
       
   634         {
       
   635         const CCalEntry& dbEntry( *( aCalEntryArray[i] ) );
       
   636         if ( aRecurrenceId.TimeUtcL() == dbEntry.RecurrenceIdL().TimeUtcL() )
       
   637             { // Entry was found in the db,
       
   638               // it may be either originating or modifying entry
       
   639             retVal = ETrue;
       
   640             aIndex = i;
       
   641             }
       
   642         }
       
   643 
       
   644     return retVal;
       
   645     }
       
   646 
       
   647 // ----------------------------------------------------------------------------
       
   648 // CMRUtilsCalDbMgr::EntryExistsInDbL
       
   649 // ----------------------------------------------------------------------------
       
   650 //   
       
   651 inline TBool CMRUtilsCalDbMgr::EntryExistsInDbL(
       
   652     const CCalEntry& aEntry,
       
   653     const CMRUtilsCalDbBase& aDb,
       
   654     RPointerArray<CCalEntry>& aCalEntryArray,
       
   655     TInt& aIndex ) const
       
   656     {
       
   657     return EntryExistsInDbL( aEntry.UidL(),
       
   658                              aEntry.RecurrenceIdL(),
       
   659                              aDb, 
       
   660                              aCalEntryArray,
       
   661                              aIndex );
       
   662     }
       
   663 
       
   664 // ----------------------------------------------------------------------------
       
   665 // CMRUtilsCalDbMgr::EvaluateExistingEntryL
       
   666 // ----------------------------------------------------------------------------
       
   667 //                                       
       
   668 MMRUtilsTombsExt::TMRUtilsDbResult CMRUtilsCalDbMgr::EvaluateExistingEntryL(
       
   669     const CCalEntry& aEntry,
       
   670     const CCalEntry& aDbEntry ) const
       
   671     {
       
   672     __ASSERT_DEBUG( aEntry.UidL() == aEntry.UidL(),
       
   673                     Panic( EPanicUnexpectedUidValue ) );
       
   674     MMRUtilsTombsExt::TMRUtilsDbResult retVal( MMRUtilsTombsExt::EUndefined );
       
   675     
       
   676     TInt seq( aEntry.SequenceNumberL() );
       
   677     TInt dbSeq( aDbEntry.SequenceNumberL() );
       
   678     TTime stamp = aEntry.DTStampL().TimeUtcL();
       
   679     TTime dbStamp = aDbEntry.DTStampL().TimeUtcL();
       
   680     
       
   681     #ifdef ICALUI_ENABLE_LOGGING
       
   682     
       
   683         LOG("CMRUtilsCalDbMgr::EvaluateExistingEntryL");
       
   684         LOG1( "CMRUtilsCalDbMgr::EvaluateExistingEntryL, new entry seq no: %d", seq );
       
   685         TBuf<KLogTimeFormatLength> timeStamp;
       
   686     	TDateTime dateTime;
       
   687     	dateTime = stamp.DateTime();
       
   688     	timeStamp.Format( KLogTimeFormat,
       
   689                           dateTime.Hour(),
       
   690                           dateTime.Minute(),
       
   691                           dateTime.Second(),
       
   692                           dateTime.MicroSecond() );
       
   693         LOG1("CMRUtilsCalDbMgr::EvaluateExistingEntryL, new entry DTStamp: %S", &timeStamp );
       
   694         LOG1( "CMRUtilsCalDbMgr::EvaluateExistingEntryL, existing entry seq no: %d", dbSeq );
       
   695         dateTime = dbStamp.DateTime();
       
   696     	timeStamp.Format( KLogTimeFormat,
       
   697                           dateTime.Hour(),
       
   698                           dateTime.Minute(),
       
   699                           dateTime.Second(),
       
   700                           dateTime.MicroSecond() );
       
   701         LOG1( "CMRUtilsCalDbMgr::EvaluateExistingEntryL, existing entry DTStamp: %S", &timeStamp );
       
   702     
       
   703     #endif // ICALUI_ENABLE_LOGGING    
       
   704         
       
   705     if ( ( seq >= dbSeq ) && ( stamp >= dbStamp ) )
       
   706         { 
       
   707         if ( ( seq == dbSeq ) && ( stamp == dbStamp ) )
       
   708             {
       
   709             retVal = MMRUtilsTombsExt::EErrorIdenticalExists;
       
   710             }
       
   711             
       
   712         else if ( aDbEntry.StatusL() == CCalEntry::ECancelled )
       
   713             {
       
   714             retVal = MMRUtilsTombsExt::EErrorCancelled;
       
   715             }
       
   716         else
       
   717             {                
       
   718             retVal = MMRUtilsTombsExt::ECheckedValidUpdate;
       
   719             }
       
   720         }
       
   721     else
       
   722         {
       
   723         retVal = MMRUtilsTombsExt::EErrorObsolete;
       
   724         }
       
   725         
       
   726     return retVal;
       
   727     }
       
   728 
       
   729 // ----------------------------------------------------------------------------
       
   730 // CMRUtilsCalDbMgr::EvaluateNewEntryL
       
   731 // This method is only used with iNormalDb
       
   732 // ----------------------------------------------------------------------------
       
   733 //
       
   734 MMRUtilsTombsExt::TMRUtilsDbResult CMRUtilsCalDbMgr::EvaluateNewEntryL(
       
   735     const CCalEntry& aEntry ) const
       
   736     {
       
   737     MMRUtilsTombsExt::TMRUtilsDbResult retVal( MMRUtilsTombsExt::EUndefined );
       
   738         
       
   739     if ( MREntryConsultant::IsModifyingEntryL( aEntry ) &&
       
   740          !IsValidNewModL( aEntry ) )
       
   741         { // recurrence id does not match to any instance of an entry
       
   742         retVal = MMRUtilsTombsExt::EErrorRecurrence;
       
   743         }
       
   744     else
       
   745         {
       
   746         retVal = MMRUtilsTombsExt::ECheckedValidNew;
       
   747         }
       
   748         
       
   749     return retVal;        
       
   750     }
       
   751     
       
   752 // ----------------------------------------------------------------------------
       
   753 // CMRUtilsCalDbMgr::EvaluateNewEntryL
       
   754 // This method is only used with iNormalDb
       
   755 // ----------------------------------------------------------------------------
       
   756 //
       
   757 TBool CMRUtilsCalDbMgr::IsValidNewModL( const CCalEntry& aModEntry ) const
       
   758     {
       
   759     TBool retVal( EFalse );    
       
   760     RCPointerArray<CCalInstance> instances; // takes ownership
       
   761     CleanupClosePushL( instances );
       
   762     TCalTime recurrenceId( aModEntry.RecurrenceIdL() );
       
   763     CalCommon::TCalTimeRange range( recurrenceId, recurrenceId );
       
   764     
       
   765     iNormalDb->InstanceView()->FindInstanceL( instances, 
       
   766                                               CalCommon::EIncludeAppts, 
       
   767 					   			              range );
       
   768     TInt count( instances.Count() );
       
   769     for ( TInt i( 0 ); i < count; ++i )
       
   770         {
       
   771         
       
   772         #ifdef ICALUI_ENABLE_LOGGING
       
   773         
       
   774             LOG("CMRUtilsCalDbMgr::IsValidNewModL");        
       
   775         	TDateTime dateTime;
       
   776             TBuf<KLogTimeFormatLength> timeStamp;        	                    
       
   777             
       
   778         	dateTime = recurrenceId.TimeUtcL().DateTime();            
       
   779         	timeStamp.Format( KLogTimeFormat,
       
   780                               dateTime.Hour(),
       
   781                               dateTime.Minute(),
       
   782                               dateTime.Second(),
       
   783                               dateTime.MicroSecond() );            
       
   784             LOG1( "CMRUtilsCalDbMgr::IsValidNewModL, mod entry uid: %S",
       
   785                   &( aModEntry.UidL() ) );                
       
   786             LOG1( "CMRUtilsCalDbMgr::IsValidNewModL, mod entry recurrence: %S",
       
   787                   &timeStamp );
       
   788             
       
   789         	dateTime = instances[i]->StartTimeL().TimeUtcL().DateTime();            
       
   790         	timeStamp.Format( KLogTimeFormat,
       
   791                               dateTime.Hour(),
       
   792                               dateTime.Minute(),
       
   793                               dateTime.Second(),
       
   794                               dateTime.MicroSecond() ); 
       
   795             LOG1( "CMRUtilsCalDbMgr::IsValidNewModL, instance uid: %S",
       
   796                   &( instances[i]->Entry().UidL() ) );
       
   797             LOG1( "CMRUtilsCalDbMgr::IsValidNewModL,instance recurrence: %S",
       
   798                   &timeStamp );
       
   799         
       
   800         #endif // ICALUI_ENABLE_LOGGING    
       
   801                 
       
   802         // When creating a new modifying entry, recurrence id must match
       
   803         // to an existing instance start time (later on start time may get
       
   804         // modified whereas recurrence id remains unchanged).
       
   805         if ( instances[i]->Entry().UidL() == aModEntry.UidL() &&
       
   806              instances[i]->StartTimeL().TimeUtcL() == recurrenceId.TimeUtcL() )
       
   807             {
       
   808             retVal = ETrue;
       
   809             break; // match found, ready to return
       
   810             }
       
   811         }
       
   812     CleanupStack::PopAndDestroy(); // instances, delete array items
       
   813     return retVal;
       
   814     }
       
   815 
       
   816 
       
   817 TBool CMRUtilsCalDbMgr::OriginatingExistInDbL( const CCalEntry& aModEntry )
       
   818     {
       
   819     TInt retVal( EFalse );
       
   820     CCalEntry* dbEntry = FetchEntryL( aModEntry.UidL(), TCalTime() );
       
   821     if ( dbEntry )
       
   822         {
       
   823         delete dbEntry;
       
   824         retVal = ETrue;
       
   825         }    
       
   826     return retVal;    
       
   827     }
       
   828     
       
   829 // End of file