--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pimappservices/calendar/client/src/calinstanceiteratoruid.cpp Tue Feb 02 10:12:19 2010 +0200
@@ -0,0 +1,440 @@
+// 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:
+//
+
+#include "calinstanceiteratoruid.h"
+#include "calsessionimpl.h"
+#include "calinstance.h"
+#include "calinstanceimpl.h"
+#include "calentryimpl.h"
+#include "calclient.h"
+#include "agmrptdef.h"
+#include "agmentry.h"
+#include "agmsimpleentry.h"
+#include "calcommonimpl.h"
+#include "agmdate.h"
+
+/** Uid instance iterator NewL
+
+@internalComponent
+*/
+CCalInstanceIteratorUid* CCalInstanceIteratorUid::NewL(const CCalInstanceViewImpl& iInstanceViewImpl, const TDesC8& aGuid, const TCalTime& aStartInstance, TUint8 aShortFileId)
+ {
+ CCalInstanceIteratorUid* self = new(ELeave) CCalInstanceIteratorUid(iInstanceViewImpl);
+ CleanupStack::PushL(self);
+ self->ConstructL(aGuid, aStartInstance, aShortFileId);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/** Uid instance iterator constructor
+
+@internalComponent
+*/
+CCalInstanceIteratorUid::CCalInstanceIteratorUid(const CCalInstanceViewImpl& iInstanceViewImpl)
+:CCalInstanceIterator(iInstanceViewImpl), iCurrentIndex(-1)
+ {
+ }
+
+/** Uid instance iterator ConstructL
+
+Fetches all the related entries to the UID and sets the currently indexed time
+
+@internalComponent
+*/
+void CCalInstanceIteratorUid::ConstructL(const TDesC8& aUid, const TCalTime& aInstanceTime, TCalCollectionId aCollectionId)
+ {
+ // record the time to use for undated todos
+ TTime now;
+ now.HomeTime();
+ iUndatedTodoTime.SetTimeLocalL(now);
+
+ // Fetch all the entries that relate to the instance
+ RPointerArray<CAgnSimpleEntry> simpleEntries;
+ TCleanSimpleEntryArray cleanSimpleEntryArray(simpleEntries, iInstanceViewImpl.GetServ());
+ CleanupStack::PushL(TCleanupItem(CCalInstanceViewImpl::DestroySimpleEntryArray, &cleanSimpleEntryArray));
+ RArray<TInt> fileIds;
+ iInstanceViewImpl.GetShortFileIdLC(fileIds);//It is in order
+ iInstanceViewImpl.GetServ().FetchSimpleEntriesByGuidL(aUid, simpleEntries, fileIds);
+ CleanupStack::PopAndDestroy(&fileIds);
+
+ const TInt KEntryCount(simpleEntries.Count());
+
+ // There must be entries associated with this UID
+ __ASSERT_ALWAYS(KEntryCount != 0, User::Leave(KErrNotFound));
+
+ TBool instanceExists(EFalse);
+
+ for (TInt i(0) ; i < KEntryCount ; ++i)
+ {
+ CCalLiteEntry* liteEntry = CCalLiteEntry::NewL(*simpleEntries[0], iInstanceViewImpl.GetServ());
+ liteEntry->IncrementRefCount();
+ simpleEntries.Remove(0);
+ TInt appendError = iCalLiteEntries.Append(liteEntry);
+ if (appendError != KErrNone)
+ {
+ liteEntry->DecrementRefCount();
+ User::Leave(appendError);
+ }
+
+ if (iInstanceViewImpl.IsValidInstanceL(liteEntry->LiteEntry(), aInstanceTime))
+ {//Add the index of the entry which has the same time as aInstanceTime into iEntryWithSameTime
+ if(liteEntry->LiteEntry().CollectionId() == aCollectionId)
+ {
+ instanceExists = ETrue;
+ iCurrentIndexTime = aInstanceTime;
+ iCurrentIndex = iEntryWithSameTime.Count();
+ }
+ iEntryWithSameTime.AppendL(i);
+ }
+ }
+
+ __ASSERT_ALWAYS(instanceExists, User::Leave(KErrNotFound));
+ CleanupStack::PopAndDestroy(); // simpleEntries
+ }
+
+/** UID instance iterator destructor
+
+@internalComponent
+*/
+CCalInstanceIteratorUid::~CCalInstanceIteratorUid()
+ {
+ // should use CleanArray of LiteEntries
+ const TInt KEntryCount(iCalLiteEntries.Count());
+ for (TInt i(0) ; i < KEntryCount ; ++i)
+ {
+ iCalLiteEntries[i]->DecrementRefCount();
+ }
+
+ iCalLiteEntries.Close();
+ iEntryWithSameTime.Close();
+ }
+
+TCalTime CCalInstanceIteratorUid::NonRptEntryInstanceTimeL(const CAgnSimpleEntry& aEntry)
+ {
+ // The entry does not have a repeat rule so it is just a single instance
+ TCalTime entryInstanceTime;
+ if (aEntry.Type() == CCalEntry::ETodo)
+ {
+ TTime completionDate = aEntry.CompletedDateUtc();
+ if (completionDate == Time::NullTTime())
+ {
+ if (!aEntry.EntryTime().IsSet())
+ {
+ entryInstanceTime = iUndatedTodoTime;
+ }
+ else
+ {
+ entryInstanceTime = CalUtils::TAgnCalendarTimeToTCalTimeL(aEntry.EntryTime());
+ }
+ }
+ else
+ {
+ if (aEntry.TimeMode() == MAgnCalendarTimeMode::EFloating)
+ {
+ entryInstanceTime.SetTimeLocalFloatingL(AgnDateTime::ConvertToLocalTimeL(completionDate));
+ }
+ else
+ {
+ entryInstanceTime.SetTimeUtcL(completionDate);
+ }
+ }
+ }
+ else
+ {
+ entryInstanceTime = CalUtils::TAgnCalendarTimeToTCalTimeL(aEntry.EntryTime());
+ }
+
+ return entryInstanceTime;
+ }
+
+/** Returns the next instance
+
+Loops through all the entries in the cached entry list and finds
+the earliest instance that appears after the current index instance time.
+
+@return The next instance
+
+@internalComponent
+*/
+CCalInstance* CCalInstanceIteratorUid::NextL()
+ {
+ CCalInstance* retInstance = NULL;
+ TInt numSameTimeEntry = iEntryWithSameTime.Count();
+ if(numSameTimeEntry >0 && iCurrentIndex < numSameTimeEntry - 1)
+ {
+ //If there are entries in iEntryWithSameTime, their instance time is same as the iCurrentIndexTime, we should return this instance.
+ return iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[iEntryWithSameTime[++iCurrentIndex]], iCurrentIndexTime);
+ }
+
+ TCalTime bestSoFar;
+ bestSoFar.SetTimeUtcL(TCalTime::MaxTime());
+ TInt thisAgnSimpleEntryIndex(KErrNotFound);
+
+ const TInt KEntryCount(iCalLiteEntries.Count());
+ TInt i(0);
+ for (; i < KEntryCount ; ++i)
+ {
+ TCalTime entryNextTime;
+ entryNextTime.SetTimeUtcL(TCalTime::MaxTime());
+
+ CAgnRptDef* thisEntryRptDef = iCalLiteEntries[i]->LiteEntry().RptDef();
+ if (thisEntryRptDef)
+ {
+ TTime entryNextTimeUtc;
+ TBool instanceFound(EFalse);
+ TTime fromTimeUtc(iCurrentIndexTime.TimeUtcL() + TTimeIntervalMicroSeconds(1));
+
+ do
+ {
+ // keep looping until we find an unexcepted instance or there are no more instances
+ instanceFound = thisEntryRptDef->NudgeNextInstanceUtcL(fromTimeUtc, entryNextTimeUtc);
+ fromTimeUtc = entryNextTimeUtc + TTimeIntervalMicroSeconds(1);
+ }
+ while (instanceFound && !thisEntryRptDef->IsAnUnexceptedInstanceL(AgnDateTime::ConvertToLocalTimeL(entryNextTimeUtc) ) );
+
+ if (instanceFound)
+ {
+ entryNextTime.SetTimeUtcL(entryNextTimeUtc);
+ }
+ }
+ else
+ {
+ TCalTime entryInstanceTime = NonRptEntryInstanceTimeL(iCalLiteEntries[i]->LiteEntry());
+
+ if (entryInstanceTime.TimeUtcL() > iCurrentIndexTime.TimeUtcL())
+ {
+ // The entry's instance time is after the current index time
+ // so it is a valid possible next instance
+ entryNextTime = entryInstanceTime;
+ }
+ }
+
+ if (entryNextTime.TimeUtcL() < bestSoFar.TimeUtcL())
+ {
+ // This time is better than best time so far so update the best so far
+ bestSoFar = entryNextTime;
+ thisAgnSimpleEntryIndex = i;
+ iEntryWithSameTime.Reset();
+ iCurrentIndex = -1;
+ }
+ else if (entryNextTime.TimeUtcL() == bestSoFar.TimeUtcL() && entryNextTime.TimeUtcL()!= TCalTime::MaxTime())
+ {
+ //Store the index of the entry which has the instance time as the "bestSoFar" time
+ iEntryWithSameTime.AppendL(i);
+ }
+ }
+
+
+ if (bestSoFar.TimeUtcL() != TCalTime::MaxTime())
+ {
+ retInstance = iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[thisAgnSimpleEntryIndex], bestSoFar);
+ iCurrentIndexTime = bestSoFar;
+ }
+
+ return retInstance;
+ }
+
+/** Returns the previous instance
+
+Loops through all the entries in the cached entry list and finds
+the latest instance that appears before the current index instance time.
+
+@return The previous instance
+
+@internalComponent
+*/
+CCalInstance* CCalInstanceIteratorUid::PreviousL()
+ {
+ CCalInstance* retInstance = NULL;
+ TInt numOfsameTimeInstance = iEntryWithSameTime.Count();
+ if(numOfsameTimeInstance > 0 && iCurrentIndex >= 1)
+ {
+ // we should return the last instance in the array to make it consistent with NextL which returns the first entry's instance.
+ return iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[iEntryWithSameTime[--iCurrentIndex]], iCurrentIndexTime);
+ }
+
+ TCalTime bestSoFar;
+ bestSoFar.SetTimeUtcL(TCalTime::MinTime());
+ TInt thisAgnSimpleEntryIndex(KErrNotFound);
+
+ const TInt KEntryCount(iCalLiteEntries.Count());
+ TInt i(0);
+ for (; i < KEntryCount ; ++i)
+ {
+ TCalTime entryPreviousTime;
+ entryPreviousTime.SetTimeUtcL(TCalTime::MinTime());
+
+ CAgnRptDef* thisEntryRptDef = iCalLiteEntries[i]->LiteEntry().RptDef();
+
+ if (thisEntryRptDef)
+ {
+ TTime entryPreviousTimeUtc(iCurrentIndexTime.TimeUtcL());
+ TBool instancefound(EFalse);
+ TTime fromTimeUtc;
+
+ do
+ {
+ fromTimeUtc = entryPreviousTimeUtc - TTimeIntervalMicroSeconds(1);
+ // keep calling until an unexcepted instance is found or there are no more instances
+ instancefound = thisEntryRptDef->NudgePreviousInstanceUtcL(fromTimeUtc, entryPreviousTimeUtc);
+ }
+ while (instancefound && !thisEntryRptDef->IsAnUnexceptedInstanceL(AgnDateTime::ConvertToLocalTimeL(entryPreviousTimeUtc) ) );
+
+ if (instancefound)
+ {
+ entryPreviousTime.SetTimeUtcL(entryPreviousTimeUtc);
+ }
+ }
+ else
+ {
+ // The entry does not have a repeat rule so it is just a single instance
+ TCalTime entryInstanceTime = NonRptEntryInstanceTimeL(iCalLiteEntries[i]->LiteEntry());
+
+ if (entryInstanceTime.TimeUtcL() < iCurrentIndexTime.TimeUtcL())
+ {
+ // The entry's instance time is before the current index time
+ // so it is a valid possible next instance
+ entryPreviousTime = entryInstanceTime;
+ }
+ }
+
+ if (entryPreviousTime.TimeUtcL() > bestSoFar.TimeUtcL())
+ {
+ // This time is better than best time so far so update the best so far
+ bestSoFar = entryPreviousTime;
+ thisAgnSimpleEntryIndex = i;
+ iEntryWithSameTime.Reset();
+ iCurrentIndex = -1;
+ }
+ else if (entryPreviousTime.TimeUtcL() == bestSoFar.TimeUtcL() && entryPreviousTime.TimeUtcL()!= TCalTime::MinTime())
+ {
+ iEntryWithSameTime.AppendL(thisAgnSimpleEntryIndex);
+ thisAgnSimpleEntryIndex = i;
+ }
+ }
+
+ if (bestSoFar.TimeUtcL() != TCalTime::MinTime())
+ {
+ retInstance = iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[thisAgnSimpleEntryIndex], bestSoFar);
+ iCurrentIndexTime = bestSoFar;
+ numOfsameTimeInstance = iEntryWithSameTime.Count();
+ if(numOfsameTimeInstance>0)
+ {
+ iCurrentIndex = numOfsameTimeInstance;
+ }
+ }
+
+ return retInstance;
+ }
+
+/** To check if there are more instance to be returned by NextL().
+
+Calls NextL() to see if if returns another instance, and then sets the current
+indexed instance time back to what it was before the call.
+
+@return ETrue if there are more instance to be returned by NextL(),
+EFalse if there are no more instance, and EFalse if there is a problem
+calculating if there are more instance to be returned by NextL().
+
+@internalComponent
+*/
+TBool CCalInstanceIteratorUid::HasMore() const
+ {
+ TBool returnValue(EFalse);
+ TRAP_IGNORE(returnValue = HasMoreL());
+ return returnValue;
+ }
+
+TBool CCalInstanceIteratorUid::HasMoreL() const
+ {
+ TBool returnValue(EFalse);
+
+ //Store the current state
+ TCalTime storedCurrentIndex = iCurrentIndexTime;
+ TInt storedArrayIndex = iCurrentIndex;
+ RArray<TInt> storedArray;
+ CleanupClosePushL(storedArray);
+ const TInt count = iEntryWithSameTime.Count();
+ for(TInt ii=0; ii<count;++ii)
+ {
+ storedArray.AppendL(iEntryWithSameTime[ii]);
+ }
+
+ //Find instances
+ CCalInstance* nextInstance = const_cast<CCalInstanceIteratorUid*>(this)->NextL();
+ returnValue = (nextInstance != NULL);
+ delete nextInstance;
+
+ // restore the state
+ const_cast<CCalInstanceIteratorUid*>(this)->iCurrentIndexTime = storedCurrentIndex;
+ iCurrentIndex = storedArrayIndex;//reset index since it could be moved in NextL
+ iEntryWithSameTime.Reset();
+ const TInt countSortedArray = storedArray.Count();
+ for(TInt ii=0; ii<countSortedArray;++ii)
+ {
+ iEntryWithSameTime.AppendL(storedArray[ii]);
+ }
+
+ CleanupStack::PopAndDestroy(&storedArray);
+
+ return returnValue;
+ }
+
+/** Instance iterator count
+
+Loops through all the entries in the cached entry list and finds each of the instance counts.
+The instance count is the sum of all the entries instances.
+
+@return The sum of the instance counts for all the entries in the cached list.
+
+@internalComponent
+*/
+TInt CCalInstanceIteratorUid::Count() const
+ {
+ TInt returnInstanceCount(0);
+ const TInt KEntryCount(iCalLiteEntries.Count());
+ for (TInt i(0) ; i < KEntryCount ; ++i)
+ {
+ CAgnRptDef* rptDef = iCalLiteEntries[i]->LiteEntry().RptDef();
+ if (rptDef)
+ {
+ // This gets all the instances generated by the repeat rule
+ TRAPD(error, returnInstanceCount += rptDef->InstanceCountL());
+ if (error)
+ {
+ // an error has occoured whilst calculating the instance count
+ // so quit and retrun the error code
+ returnInstanceCount = error;
+ break;
+ }
+
+ // Need to take off valid exception dates
+ if (rptDef->Exceptions())
+ {
+ returnInstanceCount -= rptDef->Exceptions()->Count();
+ }
+ }
+ else
+ {
+ // The entry does not have a repeat rule
+ // so it is just a single instance
+ ++returnInstanceCount;
+ }
+ }
+
+ return returnInstanceCount;
+ }
+
+