diff -r a3a1ae9acec6 -r da5135c61bad meetingrequest/mrservices/src/cesmrconflictchecker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/meetingrequest/mrservices/src/cesmrconflictchecker.cpp Wed Mar 31 21:08:33 2010 +0300 @@ -0,0 +1,444 @@ +/* +* 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#7 % +* +*/ + +#include "emailtrace.h" +#include "cesmrconflictchecker.h" +#include "cesmrcaldbmgr.h" +#include "esmrhelper.h" +#include "esmrentryhelper.h" +#include "esmrinternaluid.h" + +#include +#include +#include +#include +#include +#include + +/// 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& 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& instanceArray, + RPointerArray& 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() ); + + User::LeaveIfError( aConflictingEntries.Append( entry ) ); + CleanupStack::Pop( 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& 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 + + // Get instance views of all calendar + RPointerArray allCalenInstanceView = + iDbMgr.NormalDbAllCalenInstanceView(); + + RCPointerArray instanceArray; + CleanupClosePushL( instanceArray ); + + // 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( instanceArray, + CalCommon::EIncludeAppts, + timeRange ); + + + } + + RemoveAndDeleteNonConflictingInstancesL( + instanceArray, + aEntry.StartTimeL(), + aEntry.EndTimeL(), + aEntry.UidL(), + ERemoveSameUID ); + + CreateEntriesFromInstancesL( instanceArray, aConflicts ); + CleanupStack::PopAndDestroy(); // instanceArray + } + +// --------------------------------------------------------------------------- +// CESMRConflictChecker::FindInstancesForEntry +// --------------------------------------------------------------------------- +// +EXPORT_C void CESMRConflictChecker::FindInstancesForEntryL( + TTime aStart, + TTime aEnd, + const CCalEntry& aEntry, + TCalCollectionId aColId, + RPointerArray& aInstances ) + { + FUNC_LOG; + CCalInstanceView* instanceView = iDbMgr.InstanceViewL( aEntry ); + + RCPointerArray 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 +