--- a/meetingrequest/mrservices/src/cesmrconflictchecker.cpp Tue May 25 12:23:16 2010 +0300
+++ b/meetingrequest/mrservices/src/cesmrconflictchecker.cpp Wed Jun 09 09:22:57 2010 +0300
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+* 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"
@@ -12,7 +12,7 @@
* Contributors:
*
* Description : ESMR conflict checker implementation
-* Version : %version: e002sa33#7 %
+* Version : %version: e002sa33#9 %
*
*/
@@ -29,6 +29,7 @@
#include <calinstanceview.h>
#include <calinstanceiterator.h>
#include <ct/rcpointerarray.h>
+#include <calrrule.h>
/// Unnamed namespace for local definitions
namespace { // codescanner::namespace
@@ -94,7 +95,7 @@
CCalInstanceView* aInstanceView )
{
FUNC_LOG;
- const CalCommon::TCalViewFilter instanceFilter =
+ const CalCommon::TCalViewFilter instanceFilter =
CalCommon::EIncludeAppts;
TDateTime start = aStart.DateTime();
@@ -110,11 +111,11 @@
end.SetSecond( KZero );
end.SetMicroSecond( KZero );
TTime endTime = end;
-
- if ( TTime(start) == endTime ||
+
+ if ( TTime(start) == endTime ||
endTime < aEnd )
{
-
+
endTime += TTimeIntervalDays(1);
end = endTime.DateTime();
}
@@ -166,17 +167,17 @@
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();
+ TTime entryEndTimeLocal = instance->EndTimeL().TimeLocalL();
TPtrC8 uid( instance->Entry().UidL() );
- if ( ERemoveSameUID == aFilterType &&
+ if ( ERemoveSameUID == aFilterType &&
0 == aUid.CompareF(uid) )
{
conflictingInstance = EFalse;
@@ -201,14 +202,14 @@
}
else
{
- conflictingInstance = EFalse;
+ conflictingInstance = EFalse;
}
-
+
// Remove non-conflicting instance from instance array
if ( !conflictingInstance )
{
instanceArray.Remove(index);
- delete instance;
+ delete instance;
instance = NULL;
}
}
@@ -226,22 +227,479 @@
RPointerArray<CCalEntry>& aConflictingEntries )
{
FUNC_LOG;
- TInt instanceCount( instanceArray.Count() );
+ TInt instanceCount( instanceArray.Count() );
for ( TInt i(0); i < instanceCount; ++i )
- {
+ {
CCalEntry& parent( instanceArray[i]->Entry() );
- CCalEntry* entry = ESMRHelper::CopyEntryLC( parent,
+ CCalEntry* entry = ESMRHelper::CopyEntryLC( parent,
parent.MethodL(),
ESMRHelper::ECopyFull );
-
+
entry->SetStartAndEndTimeL( instanceArray[i]->StartTimeL(),
instanceArray[i]->EndTimeL() );
- User::LeaveIfError( aConflictingEntries.Append( entry ) );
+ 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 ========
@@ -307,38 +765,27 @@
#endif
- // Get instance views of all calendar
- RPointerArray<CCalInstanceView> allCalenInstanceView =
- iDbMgr.NormalDbAllCalenInstanceView();
-
RCPointerArray<CCalInstance> instanceArray;
CleanupClosePushL( instanceArray );
-
- // Check if there is any conflict in each calendar
- for( TInt i = 0; i < allCalenInstanceView.Count(); i++ )
+
+ if ( IsRepeatingMeetingL( aEntry, iDbMgr ) )
{
- CalCommon::TCalTimeRange timeRange =
- ResolveFetchTimeRangeL(
- aEntry.StartTimeL().TimeUtcL(),
- aEntry.EndTimeL().TimeUtcL(),
- allCalenInstanceView[i] );
-
- allCalenInstanceView[i]->FindInstanceL( instanceArray,
- CalCommon::EIncludeAppts,
- timeRange );
-
+ FindConflictsForRepeatingMeetingL(
+ aEntry,
+ instanceArray,
+ iDbMgr,
+ EFalse );
+ }
+ else
+ {
+ FindConflictsForEntryL(
+ aEntry,
+ instanceArray,
+ iDbMgr );
+ }
- }
-
- RemoveAndDeleteNonConflictingInstancesL(
- instanceArray,
- aEntry.StartTimeL(),
- aEntry.EndTimeL(),
- aEntry.UidL(),
- ERemoveSameUID );
-
CreateEntriesFromInstancesL( instanceArray, aConflicts );
- CleanupStack::PopAndDestroy(); // instanceArray
+ CleanupStack::PopAndDestroy( &instanceArray);
}
// ---------------------------------------------------------------------------
@@ -346,10 +793,10 @@
// ---------------------------------------------------------------------------
//
EXPORT_C void CESMRConflictChecker::FindInstancesForEntryL(
- TTime aStart,
+ TTime aStart,
TTime aEnd,
const CCalEntry& aEntry,
- TCalCollectionId aColId,
+ TCalCollectionId aColId,
RPointerArray<CCalEntry>& aInstances )
{
FUNC_LOG;
@@ -359,17 +806,17 @@
CleanupClosePushL( instanceArray );
// First we need the parent entry of the series ...
- CCalInstance* entryInstance = instanceView->FindInstanceL(
- aEntry.LocalUidL(),
+ CCalInstance* entryInstance = instanceView->FindInstanceL(
+ aEntry.LocalUidL(),
aEntry.StartTimeL() ); //Ownership gained
CleanupStack::PushL( entryInstance );
- CCalInstance* parentEntryInstance = instanceView->FindInstanceL(
- aEntry.LocalUidL(),
+ 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() );
@@ -378,53 +825,53 @@
// 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(),
+ 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 );
+ instanceArray.Append( instance );
}
}
CleanupStack::PopAndDestroy( instanceIterator );
- // Now the instanceArray has all instances of the aEntry,
+ // 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() ==
+
+ TBool thisInstance(
+ instance->StartTimeL().TimeLocalL() ==
aEntry.StartTimeL().TimeLocalL() &&
- instance->EndTimeL().TimeLocalL() ==
+ instance->EndTimeL().TimeLocalL() ==
aEntry.EndTimeL().TimeLocalL() );
-
+
if( thisInstance )
{
delete instance;
- instanceArray.Remove( i );
+ instanceArray.Remove( i );
}
else
{
++i;
}
}
-
+
TCalTime start;
start.SetTimeLocalL( aStart );
-
+
TCalTime end;
end.SetTimeLocalL( aEnd );
@@ -434,10 +881,10 @@
end,
aEntry.UidL(),
EIncludeSameUID );
-
+
CreateEntriesFromInstancesL( instanceArray, aInstances );
-
- CleanupStack::PopAndDestroy(); // instanceArray
+
+ CleanupStack::PopAndDestroy(); // instanceArray
}
// EOF