--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/meetingrequest/mrservices/src/cesmrconflictchecker.cpp Wed Sep 01 12:28:57 2010 +0100
@@ -0,0 +1,891 @@
+/*
+* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description : ESMR conflict checker implementation
+* Version : %version: e002sa33#9 %
+*
+*/
+
+#include "emailtrace.h"
+#include "cesmrconflictchecker.h"
+#include "cesmrcaldbmgr.h"
+#include "esmrhelper.h"
+#include "esmrentryhelper.h"
+#include "esmrinternaluid.h"
+
+#include <calcommon.h>
+#include <calinstance.h>
+#include <calentryview.h>
+#include <calinstanceview.h>
+#include <calinstanceiterator.h>
+#include <ct/rcpointerarray.h>
+#include <calrrule.h>
+
+/// Unnamed namespace for local definitions
+namespace { // codescanner::namespace
+
+// Definition for zero
+const TInt KZero(0);
+
+/** Defines instace filter type */
+enum TInstanceFilter
+ {
+ EIncludeSameUID,
+ ERemoveSameUID
+ };
+
+#ifdef _DEBUG
+
+// Literal for panic texts
+_LIT( KESMRConflictCheckerTxt, "ESMRConflictChecker" );
+
+/** Enumeration for panic codes */
+enum TESMRConflictCheckerPanic
+ {
+ // Input entry is not appointment
+ EESMRConflictCheckerInvalidEntryType
+ };
+
+/**
+ * Thows system wide panic.
+ * @param aPanic Panic code.
+ */
+void Panic( TESMRConflictCheckerPanic aPanic )
+ {
+
+ User::Panic( KESMRConflictCheckerTxt, aPanic );
+ }
+
+#else
+
+/**
+ * Thows system wide leave.
+ * @param aError Leave code.
+ */
+void Leave( TInt aError )
+ {
+
+ User::Leave( aError );
+ }
+
+#endif
+
+/**
+ * Resolves time range for possible conflicting entries. Instance view
+ * is used for resolving the time range.
+ *
+ * @param aStart Start time
+ * @param aEnd End time
+ * @param aInstanceView Pointer to calendar db instance view
+ * @return Time range for possible conflicting entries
+ */
+CalCommon::TCalTimeRange ResolveFetchTimeRangeL(
+ TTime aStart,
+ TTime aEnd,
+ CCalInstanceView* aInstanceView )
+ {
+ FUNC_LOG;
+ const CalCommon::TCalViewFilter instanceFilter =
+ CalCommon::EIncludeAppts;
+
+ TDateTime start = aStart.DateTime();
+ TDateTime end = aEnd.DateTime();
+
+ start.SetHour( KZero );
+ start.SetMinute( KZero );
+ start.SetSecond( KZero );
+ start.SetMicroSecond( KZero );
+
+ end.SetHour( KZero );
+ end.SetMinute( KZero );
+ end.SetSecond( KZero );
+ end.SetMicroSecond( KZero );
+ TTime endTime = end;
+
+ if ( TTime(start) == endTime ||
+ endTime < aEnd )
+ {
+
+ endTime += TTimeIntervalDays(1);
+ end = endTime.DateTime();
+ }
+
+ TCalTime rangeStart;
+ rangeStart.SetTimeLocalL( start );
+
+ TCalTime instanceTime = aInstanceView->PreviousInstanceL(
+ instanceFilter,
+ rangeStart );
+
+ if ( Time::NullTTime() != instanceTime.TimeUtcL() )
+ {
+ rangeStart = instanceTime;
+ }
+
+ TCalTime rangeEnd;
+ rangeEnd.SetTimeLocalL( end );
+
+ instanceTime = aInstanceView->NextInstanceL(
+ instanceFilter,
+ rangeEnd );
+
+ if ( instanceTime.TimeLocalL() != Time::NullTTime() )
+ {
+ rangeEnd = instanceTime;
+ }
+
+ return CalCommon::TCalTimeRange( rangeStart, rangeEnd );
+ }
+
+/**
+ * Removes and deletes the entries, which do not conflict with
+ * entry. Entry is considered to be conflicting entry if starts or
+ * ends between aEntry's start and end time.
+ *
+ * @param aEntries Reference to entries, which may conflict
+ * @param aEntry Reference to entry, which confilcts are resolved.
+ */
+void RemoveAndDeleteNonConflictingInstancesL(
+ RPointerArray<CCalInstance>& instanceArray,
+ TCalTime aStartTime,
+ TCalTime aEndTime,
+ const TDesC8& aUid,
+ TInstanceFilter aFilterType )
+ {
+ FUNC_LOG;
+ TInt index(0);
+
+ TTime startTimeLocal = aStartTime.TimeLocalL();
+ TTime endTimeLocal = aEndTime.TimeLocalL();
+
+ while( index < instanceArray.Count() )
+ {
+ TBool conflictingInstance( ETrue );
+ CCalInstance* instance = instanceArray[index];
+
+ TTime entryStartTimeLocal = instance->StartTimeL().TimeLocalL();
+ TTime entryEndTimeLocal = instance->EndTimeL().TimeLocalL();
+
+ TPtrC8 uid( instance->Entry().UidL() );
+ if ( ERemoveSameUID == aFilterType &&
+ 0 == aUid.CompareF(uid) )
+ {
+ conflictingInstance = EFalse;
+ }
+ else if ( entryStartTimeLocal >= startTimeLocal &&
+ entryStartTimeLocal < endTimeLocal )
+ {
+ // Entry starts during another entry
+ index++;
+ }
+ else if ( entryEndTimeLocal > startTimeLocal &&
+ entryEndTimeLocal <= endTimeLocal )
+ {
+ // Entry ends during another entry
+ index++;
+ }
+ else if ( entryStartTimeLocal < startTimeLocal &&
+ entryEndTimeLocal > endTimeLocal )
+ {
+ // Antry starts and ends during another entry
+ index++;
+ }
+ else
+ {
+ conflictingInstance = EFalse;
+ }
+
+ // Remove non-conflicting instance from instance array
+ if ( !conflictingInstance )
+ {
+ instanceArray.Remove(index);
+ delete instance;
+ instance = NULL;
+ }
+ }
+ }
+
+/**
+ * Creates calendar entries from the conflicting instances
+ * and stores the created entries into entry array.
+ * Ownership of the created entries is transferred to caller.
+ * @param aInstanceArray Reference to instance array
+ * @param aConflictingEntries Reference to entry array.
+ */
+void CreateEntriesFromInstancesL(
+ RPointerArray<CCalInstance>& instanceArray,
+ RPointerArray<CCalEntry>& aConflictingEntries )
+ {
+ FUNC_LOG;
+ TInt instanceCount( instanceArray.Count() );
+ for ( TInt i(0); i < instanceCount; ++i )
+ {
+ CCalEntry& parent( instanceArray[i]->Entry() );
+ CCalEntry* entry = ESMRHelper::CopyEntryLC( parent,
+ parent.MethodL(),
+ ESMRHelper::ECopyFull );
+
+ entry->SetStartAndEndTimeL( instanceArray[i]->StartTimeL(),
+ instanceArray[i]->EndTimeL() );
+
+ aConflictingEntries.AppendL( entry );
+ CleanupStack::Pop( entry );
+ }
+ }
+
+/**
+ * Checks if entry is repeating.
+ * @return ETrue if entry is repeating
+ */
+TBool IsRepeatingMeetingL( const CCalEntry& aEntry,
+ MESMRCalDbMgr& aDb )
+ {
+ FUNC_LOG;
+
+ TBool recurrent( EFalse );
+
+ CCalInstance* instance = aDb.FindInstanceL( aEntry );
+
+ if ( instance )
+ {
+ CleanupStack::PushL( instance );
+ recurrent = ESMREntryHelper::IsRepeatingMeetingL( instance->Entry() );
+ CleanupStack::PopAndDestroy( instance );
+ }
+ else
+ {
+ recurrent = ESMREntryHelper::IsRepeatingMeetingL( aEntry );
+ }
+
+ return recurrent;
+ }
+
+/**
+ * Finds conflicts for entry
+ */
+void FindConflictsForEntryL(
+ const CCalEntry& aEntry,
+ RPointerArray< CCalInstance >& aInstances,
+ MESMRCalDbMgr& aDb )
+ {
+ FUNC_LOG;
+
+ // Get instance views of all calendar
+ RPointerArray<CCalInstanceView> allCalenInstanceView =
+ aDb.NormalDbAllCalenInstanceView();
+
+ // Check if there is any conflict in each calendar
+ for( TInt i = 0; i < allCalenInstanceView.Count(); i++ )
+ {
+ CalCommon::TCalTimeRange timeRange =
+ ResolveFetchTimeRangeL(
+ aEntry.StartTimeL().TimeUtcL(),
+ aEntry.EndTimeL().TimeUtcL(),
+ allCalenInstanceView[i] );
+
+ allCalenInstanceView[i]->FindInstanceL(
+ aInstances,
+ CalCommon::EIncludeAppts,
+ timeRange );
+ }
+
+ RemoveAndDeleteNonConflictingInstancesL(
+ aInstances,
+ aEntry.StartTimeL(),
+ aEntry.EndTimeL(),
+ aEntry.UidL(),
+ ERemoveSameUID );
+ }
+
+/**
+ * Moves instances from an array to another.
+ */
+void MoveInstancesL(
+ RPointerArray< CCalInstance >& aFrom,
+ RPointerArray< CCalInstance >& aTo )
+ {
+ FUNC_LOG;
+
+ aTo.ReserveL( aTo.Count() + aFrom.Count() );
+ while ( aFrom.Count() )
+ {
+ aTo.AppendL( aFrom[ 0 ] );
+ aFrom.Remove( 0 );
+ }
+ }
+
+/**
+ * Finds conflicts based on Daily recurrence.
+ *
+ */
+void FindConflictsForDailyRRuleL(
+ CCalEntry& aEntry,
+ RPointerArray< CCalInstance >& aInstances,
+ MESMRCalDbMgr& aDb,
+ TBool aFindAllConflicts )
+ {
+ FUNC_LOG;
+
+ TCalRRule rRule;
+ aEntry.GetRRuleL( rRule );
+ RCPointerArray< CCalInstance > tmpInstanceArray;
+ CleanupClosePushL( tmpInstanceArray );
+
+ // Entry start and end time
+ TTime start( aEntry.StartTimeL().TimeUtcL() );
+ TTime end( aEntry.EndTimeL().TimeUtcL() );
+
+ if ( rRule.Count() )
+ {
+ for ( TInt i = 0; i < rRule.Count(); ++i )
+ {
+ // Set each occurence start and end time on entry
+ TTimeIntervalDays interval( i * rRule.Interval() );
+ TCalTime startTime;
+ startTime.SetTimeUtcL( start + interval );
+ TCalTime endTime;
+ endTime.SetTimeUtcL( end + interval );
+ aEntry.SetStartAndEndTimeL(
+ startTime,
+ endTime );
+
+ // Find conflicts for this occurence
+ FindConflictsForEntryL( aEntry, tmpInstanceArray, aDb );
+
+ if ( tmpInstanceArray.Count() )
+ {
+ MoveInstancesL( tmpInstanceArray, aInstances );
+ if ( !aFindAllConflicts )
+ {
+ break;
+ }
+ }
+ }
+ }
+ else if ( rRule.Until().TimeUtcL() != Time::NullTTime() )
+ {
+ TTime until( rRule.Until().TimeUtcL() );
+ TTime start( aEntry.StartTimeL().TimeUtcL() );
+ TTime end( aEntry.EndTimeL().TimeUtcL() );
+ TTimeIntervalDays interval( rRule.Interval() );
+
+ // Loop while start time is before until time
+ while ( start <= until )
+ {
+ // Set start and end time for occurence
+ TCalTime startTime;
+ startTime.SetTimeUtcL( start );
+ TCalTime endTime;
+ endTime.SetTimeUtcL( end );
+ aEntry.SetStartAndEndTimeL(
+ startTime,
+ endTime );
+
+ // Find conflicts
+ FindConflictsForEntryL( aEntry, tmpInstanceArray, aDb );
+
+ if ( tmpInstanceArray.Count() )
+ {
+ MoveInstancesL( tmpInstanceArray, aInstances );
+ if ( !aFindAllConflicts )
+ {
+ break;
+ }
+ }
+
+ // Move to next occurence
+ start += interval;
+ end += interval;
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &tmpInstanceArray );
+ }
+
+/**
+ * Finds conflicts based on Weekly recurrence.
+ */
+void FindConflictsForWeeklyRRuleL(
+ CCalEntry& aEntry,
+ RPointerArray< CCalInstance >& aInstances,
+ MESMRCalDbMgr& aDb,
+ TBool aFindAllConflicts )
+ {
+ FUNC_LOG;
+
+ TCalRRule rRule;
+ aEntry.GetRRuleL( rRule );
+
+ // Tmp array for conflic instances
+ RCPointerArray< CCalInstance > tmpInstanceArray;
+ CleanupClosePushL( tmpInstanceArray );
+
+ // Array of recurrence days
+ RArray< TDay > days;
+ CleanupClosePushL( days );
+ rRule.GetByDayL( days );
+
+ // Recurrence start time
+ TTime start( aEntry.StartTimeL().TimeUtcL() );
+ // Recurrence end time
+ TTime end( aEntry.EndTimeL().TimeUtcL() );
+ const TTimeIntervalDays KWeek( 7 );
+ TDay startDayOfWeek( start.DayNoInWeek() );
+
+ // Instance duration
+ TTimeIntervalMinutes duration;
+ end.MinutesFrom( start, duration );
+
+ if ( rRule.Count() )
+ {
+ for ( TInt i = 0; i < rRule.Count(); ++i )
+ {
+ // Calculate weekly start time
+ TTimeIntervalDays interval( i* KWeek.Int() );
+ TDateTime date( TTime( start + interval ).DateTime() );
+ date.SetDay( date.Day() - startDayOfWeek );
+ TTime weekStartTime( date );
+
+ for ( TInt j = 0; j < days.Count(); ++j )
+ {
+ // Iterate through days of week
+ TTime entryStartTime( weekStartTime + TTimeIntervalDays( days[ j ] ) );
+
+ if ( start <= entryStartTime )
+ {
+ // Start time is in recurrence range
+ // Calcualte end time
+ TCalTime startCalTime;
+ startCalTime.SetTimeUtcL( entryStartTime );
+ TCalTime endCalTime;
+ endCalTime.SetTimeUtcL( entryStartTime + duration );
+ aEntry.SetStartAndEndTimeL( startCalTime, endCalTime );
+
+ // Find conflicts of for entry and move them to result array
+ FindConflictsForEntryL( aEntry, tmpInstanceArray, aDb );
+
+ if ( tmpInstanceArray.Count() )
+ {
+ MoveInstancesL( tmpInstanceArray, aInstances );
+ if ( !aFindAllConflicts )
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !aFindAllConflicts && aInstances.Count() )
+ {
+ break;
+ }
+ }
+ }
+ else if ( rRule.Until().TimeUtcL() != Time::NullTTime() )
+ {
+ TDateTime date( start.DateTime() );
+ date.SetDay( date.Day() - startDayOfWeek );
+ TTime weekStartTime( date );
+ TTime until( rRule.Until().TimeUtcL() );
+
+ while ( weekStartTime < until )
+ {
+ for ( TInt j = 0; j < days.Count(); ++j )
+ {
+ // Iterate through days of week
+ TTime entryStartTime( weekStartTime + TTimeIntervalDays( days[ j ] ) );
+
+ if ( start <= entryStartTime )
+ {
+ // Start time is in recurrence range
+ // Calculate end time
+ TCalTime startCalTime;
+ startCalTime.SetTimeUtcL( entryStartTime );
+ TCalTime endCalTime;
+ endCalTime.SetTimeUtcL( entryStartTime + duration );
+ aEntry.SetStartAndEndTimeL( startCalTime, endCalTime );
+
+ // Find conflicts of for entry and move them to result array
+ FindConflictsForEntryL( aEntry, tmpInstanceArray, aDb );
+
+ if ( tmpInstanceArray.Count() )
+ {
+ MoveInstancesL( tmpInstanceArray, aInstances );
+ if ( !aFindAllConflicts )
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !aFindAllConflicts && aInstances.Count() )
+ {
+ break;
+ }
+ else
+ {
+ weekStartTime += KWeek;
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &days );
+ CleanupStack::PopAndDestroy( &tmpInstanceArray );
+ }
+
+/**
+ * Finds conflict for recurrent entry
+ */
+void FindConflictsForRepeatingMeetingL(
+ const CCalEntry& aEntry,
+ RPointerArray< CCalInstance >& aInstances,
+ MESMRCalDbMgr& aDb,
+ TBool aFindAllConflicts )
+ {
+ FUNC_LOG;
+
+ CCalInstance* instance = aDb.FindInstanceL( aEntry );
+
+ if ( instance ) // Instance is stored
+ {
+ CleanupStack::PushL( instance );
+ RCPointerArray< CCalInstance > tmpInstanceArray;
+ CleanupClosePushL( tmpInstanceArray );
+
+ CCalEntry& parent = instance->Entry();
+ CCalInstanceView* instanceView = aDb.InstanceViewL( parent );
+ CCalInstanceIterator* iterator = instanceView->FindInstanceByUidL(
+ parent.UidL(),
+ parent.StartTimeL() );
+ CleanupStack::PushL( iterator );
+ CCalEntry* entry = ESMRHelper::CopyEntryLC(
+ parent,
+ parent.MethodL(),
+ ESMRHelper::ECopyFull );
+
+ while ( iterator->HasMore() )
+ {
+ CCalInstance* next = iterator->NextL();
+ CleanupStack::PushL( next );
+ entry->SetStartAndEndTimeL( next->StartTimeL(), next->EndTimeL() );
+ CleanupStack::PopAndDestroy( next );
+ FindConflictsForEntryL( *entry,
+ tmpInstanceArray,
+ aDb );
+
+ if ( tmpInstanceArray.Count() )
+ {
+ MoveInstancesL( tmpInstanceArray, aInstances );
+
+ if ( !aFindAllConflicts )
+ {
+ break;
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy( entry );
+
+ CleanupStack::PopAndDestroy( iterator );
+
+ if ( aFindAllConflicts
+ || !aInstances.Count() )
+ {
+ // Find conflicts also for parent entry
+ FindConflictsForEntryL( parent, tmpInstanceArray, aDb );
+ MoveInstancesL( tmpInstanceArray, aInstances );
+ }
+
+ CleanupStack::PopAndDestroy( &tmpInstanceArray );
+ CleanupStack::PopAndDestroy( instance );
+ }
+ else // Entry is not stored yet
+ {
+ CCalEntry* entry = ESMRHelper::CopyEntryLC(
+ aEntry,
+ aEntry.MethodL(),
+ ESMRHelper::ECopyFull );
+
+ TCalRRule rRule;
+ if ( aEntry.GetRRuleL( rRule ) )
+ {
+ switch ( rRule.Type() )
+ {
+ case TCalRRule::EDaily:
+ {
+ FindConflictsForDailyRRuleL(
+ *entry,
+ aInstances,
+ aDb,
+ aFindAllConflicts );
+ break;
+ }
+ case TCalRRule::EWeekly:
+ {
+ FindConflictsForWeeklyRRuleL(
+ *entry,
+ aInstances,
+ aDb,
+ aFindAllConflicts );
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // Entry has RDates set
+ RCPointerArray< CCalInstance > tmpInstanceArray;
+ CleanupClosePushL( tmpInstanceArray );
+
+ RArray< TCalTime > rDates;
+ CleanupClosePushL( rDates );
+ aEntry.GetRDatesL( rDates );
+
+ // Get entry start time, end time and duration
+ TTime start( aEntry.StartTimeL().TimeUtcL() );
+ TTime end( aEntry.EndTimeL().TimeUtcL() );
+ TTimeIntervalMinutes duration(0);
+ end.MinutesFrom(
+ start,
+ duration );
+
+ for ( TInt i = 0; i < rDates.Count(); ++i )
+ {
+ // Set start and end times for entry
+ TCalTime startTime( rDates[ i ] );
+ TCalTime endTime;
+ endTime.SetTimeUtcL( startTime.TimeUtcL() + duration );
+ entry->SetStartAndEndTimeL( startTime, endTime );
+
+ // Find conflicts
+ FindConflictsForEntryL( *entry, tmpInstanceArray, aDb );
+
+ if ( tmpInstanceArray.Count() )
+ {
+ MoveInstancesL( tmpInstanceArray, aInstances );
+ if ( !aFindAllConflicts )
+ {
+ break;
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &rDates );
+
+ if ( aFindAllConflicts
+ || aInstances.Count() == 0 )
+ {
+ // Find conflicts for parent entry
+ FindConflictsForEntryL( aEntry, tmpInstanceArray, aDb );
+ MoveInstancesL( tmpInstanceArray, aInstances );
+ }
+
+ CleanupStack::PopAndDestroy( &tmpInstanceArray );
+ }
+
+ CleanupStack::PopAndDestroy( entry );
+ }
+ }
+
+} // namespace
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CESMRConflictChecker::CESMRConflictChecker
+// ---------------------------------------------------------------------------
+//
+inline CESMRConflictChecker::CESMRConflictChecker(
+ MESMRCalDbMgr& aDbMgr ) :
+ iDbMgr( aDbMgr )
+ {
+ FUNC_LOG;
+ // Not implementation yet
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRConflictChecker::~CESMRConflictChecker
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CESMRConflictChecker::~CESMRConflictChecker()
+ {
+ FUNC_LOG;
+ // Not implementation yet
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRConflictChecker::NewL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CESMRConflictChecker* CESMRConflictChecker::NewL(
+ MESMRCalDbMgr& aDbMgr )
+ {
+ FUNC_LOG;
+ CESMRConflictChecker* self =
+ new (ELeave) CESMRConflictChecker(aDbMgr);
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRConflictChecker::FindConflictsL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRConflictChecker::FindConflictsL(
+ const CCalEntry& aEntry,
+ RPointerArray<CCalEntry>& aConflicts )
+ {
+ FUNC_LOG;
+
+ // Checking input parameters
+#ifdef _DEBUG
+
+ __ASSERT_DEBUG(
+ CCalEntry::EAppt == aEntry.EntryTypeL(),
+ Panic(EESMRConflictCheckerInvalidEntryType) );
+
+#else
+
+ if ( CCalEntry::EAppt != aEntry.EntryTypeL() )
+ {
+ Leave( KErrArgument );
+ }
+
+#endif
+
+ RCPointerArray<CCalInstance> instanceArray;
+ CleanupClosePushL( instanceArray );
+
+ if ( IsRepeatingMeetingL( aEntry, iDbMgr ) )
+ {
+ FindConflictsForRepeatingMeetingL(
+ aEntry,
+ instanceArray,
+ iDbMgr,
+ EFalse );
+ }
+ else
+ {
+ FindConflictsForEntryL(
+ aEntry,
+ instanceArray,
+ iDbMgr );
+ }
+
+ CreateEntriesFromInstancesL( instanceArray, aConflicts );
+ CleanupStack::PopAndDestroy( &instanceArray);
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRConflictChecker::FindInstancesForEntry
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRConflictChecker::FindInstancesForEntryL(
+ TTime aStart,
+ TTime aEnd,
+ const CCalEntry& aEntry,
+ TCalCollectionId aColId,
+ RPointerArray<CCalEntry>& aInstances )
+ {
+ FUNC_LOG;
+ CCalInstanceView* instanceView = iDbMgr.InstanceViewL( aEntry );
+
+ RCPointerArray<CCalInstance> instanceArray;
+ CleanupClosePushL( instanceArray );
+
+ // First we need the parent entry of the series ...
+ CCalInstance* entryInstance = instanceView->FindInstanceL(
+ aEntry.LocalUidL(),
+ aEntry.StartTimeL() ); //Ownership gained
+ CleanupStack::PushL( entryInstance );
+
+ CCalInstance* parentEntryInstance = instanceView->FindInstanceL(
+ aEntry.LocalUidL(),
+ entryInstance->Entry().StartTimeL() );
+ CleanupStack::PopAndDestroy( entryInstance );
+ CleanupStack::PushL( parentEntryInstance );
+
+ // ... And the parent entry instances start time
+ TCalTime firstIntanceStartTime( parentEntryInstance->StartTimeL() );
+
+ CleanupStack::Pop( parentEntryInstance ); // ownership given to instanceArray
+ instanceArray.Append( parentEntryInstance );
+
+ // Let's get all instances which have same uid and collection id
+ // as the aEntry to an iterator.
+ CCalInstanceIterator* instanceIterator = instanceView->FindInstanceByUidL(
+ aColId,
+ aEntry.UidL(),
+ firstIntanceStartTime );
+ CleanupStack::PushL( instanceIterator );
+
+ TInt count( instanceIterator->Count() );
+
+ for( TInt i = 0; i < count; ++i )
+ {
+ CCalInstance* instance = NULL;
+ TRAPD( err, instance = instanceIterator->NextL() ); //Ownership gained
+ if( !err && instance )
+ {
+ instanceArray.Append( instance );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( instanceIterator );
+
+ // Now the instanceArray has all instances of the aEntry,
+ // let's remove this instance == instance of aEntry, from the array
+ TInt i( 0 );
+ while( i < instanceArray.Count() )
+ {
+ CCalInstance* instance = instanceArray[i];
+
+ TBool thisInstance(
+ instance->StartTimeL().TimeLocalL() ==
+ aEntry.StartTimeL().TimeLocalL() &&
+ instance->EndTimeL().TimeLocalL() ==
+ aEntry.EndTimeL().TimeLocalL() );
+
+ if( thisInstance )
+ {
+ delete instance;
+ instanceArray.Remove( i );
+ }
+ else
+ {
+ ++i;
+ }
+ }
+
+ TCalTime start;
+ start.SetTimeLocalL( aStart );
+
+ TCalTime end;
+ end.SetTimeLocalL( aEnd );
+
+ RemoveAndDeleteNonConflictingInstancesL(
+ instanceArray,
+ start,
+ end,
+ aEntry.UidL(),
+ EIncludeSameUID );
+
+ CreateEntriesFromInstancesL( instanceArray, aInstances );
+
+ CleanupStack::PopAndDestroy(); // instanceArray
+ }
+
+// EOF
+