meetingrequest/mrservices/src/cesmrconflictchecker.cpp
branchRCL_3
changeset 12 4ce476e64c59
child 18 6b8f3b30d0ec
--- /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 <calcommon.h>
+#include <calinstance.h>
+#include <calentryview.h>
+#include <calinstanceview.h>
+#include <calinstanceiterator.h>
+#include <ct/rcpointerarray.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() );
+
+        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<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
+
+    // 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++ )
+        {
+        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<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
+