pimappservices/calendar/client/src/calinstanceiteratoruid.cpp
changeset 0 f979ecb2b13e
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "calinstanceiteratoruid.h"
       
    17 #include "calsessionimpl.h"
       
    18 #include "calinstance.h"
       
    19 #include "calinstanceimpl.h"
       
    20 #include "calentryimpl.h"
       
    21 #include "calclient.h"
       
    22 #include "agmrptdef.h"
       
    23 #include "agmentry.h"
       
    24 #include "agmsimpleentry.h"
       
    25 #include "calcommonimpl.h"
       
    26 #include "agmdate.h"
       
    27 
       
    28 /** Uid instance iterator NewL
       
    29 
       
    30 @internalComponent
       
    31 */
       
    32 CCalInstanceIteratorUid* CCalInstanceIteratorUid::NewL(const CCalInstanceViewImpl& iInstanceViewImpl, const TDesC8& aGuid, const TCalTime& aStartInstance, TUint8 aShortFileId)
       
    33 	{
       
    34 	CCalInstanceIteratorUid* self = new(ELeave) CCalInstanceIteratorUid(iInstanceViewImpl);
       
    35 	CleanupStack::PushL(self);
       
    36 	self->ConstructL(aGuid, aStartInstance, aShortFileId);
       
    37 	CleanupStack::Pop(self);
       
    38 	return self;
       
    39 	}
       
    40 
       
    41 /** Uid instance iterator constructor
       
    42 
       
    43 @internalComponent
       
    44 */
       
    45 CCalInstanceIteratorUid::CCalInstanceIteratorUid(const CCalInstanceViewImpl& iInstanceViewImpl)
       
    46 :CCalInstanceIterator(iInstanceViewImpl), iCurrentIndex(-1)
       
    47 	{
       
    48 	}
       
    49 
       
    50 /** Uid instance iterator ConstructL
       
    51 
       
    52 Fetches all the related entries to the UID and sets the currently indexed time
       
    53 
       
    54 @internalComponent
       
    55 */
       
    56 void CCalInstanceIteratorUid::ConstructL(const TDesC8& aUid, const TCalTime& aInstanceTime, TCalCollectionId aCollectionId)
       
    57 	{
       
    58 	// record the time to use for undated todos
       
    59 	TTime now;
       
    60 	now.HomeTime();
       
    61 	iUndatedTodoTime.SetTimeLocalL(now);
       
    62 	
       
    63 	// Fetch all the entries that relate to the instance
       
    64 	RPointerArray<CAgnSimpleEntry> simpleEntries;
       
    65 	TCleanSimpleEntryArray cleanSimpleEntryArray(simpleEntries, iInstanceViewImpl.GetServ());
       
    66 	CleanupStack::PushL(TCleanupItem(CCalInstanceViewImpl::DestroySimpleEntryArray, &cleanSimpleEntryArray));
       
    67 	RArray<TInt> fileIds;
       
    68 	iInstanceViewImpl.GetShortFileIdLC(fileIds);//It is in order 
       
    69 	iInstanceViewImpl.GetServ().FetchSimpleEntriesByGuidL(aUid, simpleEntries, fileIds);
       
    70 	CleanupStack::PopAndDestroy(&fileIds);
       
    71 	
       
    72 	const TInt KEntryCount(simpleEntries.Count());
       
    73 	
       
    74 	// There must be entries associated with this UID
       
    75 	__ASSERT_ALWAYS(KEntryCount != 0, User::Leave(KErrNotFound));
       
    76 	
       
    77 	TBool instanceExists(EFalse);
       
    78 	
       
    79 	for (TInt i(0) ; i < KEntryCount ; ++i)
       
    80 		{
       
    81 		CCalLiteEntry* liteEntry = CCalLiteEntry::NewL(*simpleEntries[0], iInstanceViewImpl.GetServ());
       
    82 		liteEntry->IncrementRefCount();
       
    83 		simpleEntries.Remove(0);
       
    84 		TInt appendError = iCalLiteEntries.Append(liteEntry);	
       
    85 		if (appendError != KErrNone)
       
    86 			{
       
    87 			liteEntry->DecrementRefCount();
       
    88 			User::Leave(appendError);
       
    89 			}
       
    90 		
       
    91 		if (iInstanceViewImpl.IsValidInstanceL(liteEntry->LiteEntry(), aInstanceTime))
       
    92 			{//Add the index of the entry which has the same time as aInstanceTime into iEntryWithSameTime
       
    93 			if(liteEntry->LiteEntry().CollectionId() == aCollectionId)
       
    94 				{
       
    95 				instanceExists = ETrue;
       
    96 				iCurrentIndexTime = aInstanceTime;
       
    97 				iCurrentIndex = iEntryWithSameTime.Count();
       
    98 				}
       
    99 			iEntryWithSameTime.AppendL(i);
       
   100 			}
       
   101 		}
       
   102 	
       
   103 	__ASSERT_ALWAYS(instanceExists, User::Leave(KErrNotFound));
       
   104 	CleanupStack::PopAndDestroy(); // simpleEntries
       
   105 	}
       
   106 
       
   107 /** UID instance iterator destructor
       
   108 
       
   109 @internalComponent
       
   110 */
       
   111 CCalInstanceIteratorUid::~CCalInstanceIteratorUid()
       
   112 	{
       
   113 	// should use CleanArray of LiteEntries 
       
   114 	const TInt KEntryCount(iCalLiteEntries.Count());
       
   115 	for (TInt i(0) ; i < KEntryCount ; ++i)
       
   116 		{
       
   117 		iCalLiteEntries[i]->DecrementRefCount(); 
       
   118 		}
       
   119 	
       
   120 	iCalLiteEntries.Close();
       
   121 	iEntryWithSameTime.Close();
       
   122 	}
       
   123 
       
   124 TCalTime CCalInstanceIteratorUid::NonRptEntryInstanceTimeL(const CAgnSimpleEntry& aEntry)
       
   125 	{	
       
   126 	// The entry does not have a repeat rule so it is just a single instance
       
   127 	TCalTime entryInstanceTime;
       
   128 	if (aEntry.Type() == CCalEntry::ETodo)
       
   129 		{
       
   130 		TTime completionDate = aEntry.CompletedDateUtc();
       
   131 		if (completionDate == Time::NullTTime())
       
   132 			{
       
   133 			if (!aEntry.EntryTime().IsSet())
       
   134 				{
       
   135 				entryInstanceTime = iUndatedTodoTime;
       
   136 				}
       
   137 			else
       
   138 				{
       
   139 				entryInstanceTime = CalUtils::TAgnCalendarTimeToTCalTimeL(aEntry.EntryTime());
       
   140 				}
       
   141 			}
       
   142 		else
       
   143 			{
       
   144 			if (aEntry.TimeMode() == MAgnCalendarTimeMode::EFloating)
       
   145 				{
       
   146 				entryInstanceTime.SetTimeLocalFloatingL(AgnDateTime::ConvertToLocalTimeL(completionDate));
       
   147 				}
       
   148 			else
       
   149 				{
       
   150 				entryInstanceTime.SetTimeUtcL(completionDate);
       
   151 				}
       
   152 			}
       
   153 		}
       
   154 	else
       
   155 		{
       
   156 		entryInstanceTime = CalUtils::TAgnCalendarTimeToTCalTimeL(aEntry.EntryTime());
       
   157 		}
       
   158 	
       
   159 	return entryInstanceTime;
       
   160 	}
       
   161 
       
   162 /** Returns the next instance
       
   163 
       
   164 Loops through all the entries in the cached entry list and finds
       
   165 the earliest instance that appears after the current index instance time.
       
   166 
       
   167 @return The next instance
       
   168 
       
   169 @internalComponent
       
   170 */
       
   171 CCalInstance* CCalInstanceIteratorUid::NextL()
       
   172 	{
       
   173 	CCalInstance* retInstance = NULL;
       
   174 	TInt numSameTimeEntry = iEntryWithSameTime.Count();
       
   175 	if(numSameTimeEntry >0 && iCurrentIndex < numSameTimeEntry - 1)
       
   176 		{
       
   177 		//If there are entries in iEntryWithSameTime, their instance time is same as the iCurrentIndexTime, we should return this instance. 
       
   178 		return iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[iEntryWithSameTime[++iCurrentIndex]], iCurrentIndexTime);
       
   179 		}
       
   180 	
       
   181 	TCalTime bestSoFar;
       
   182 	bestSoFar.SetTimeUtcL(TCalTime::MaxTime());
       
   183 	TInt thisAgnSimpleEntryIndex(KErrNotFound);
       
   184 	
       
   185 	const TInt KEntryCount(iCalLiteEntries.Count());
       
   186 	TInt i(0);
       
   187 	for (; i < KEntryCount ; ++i)
       
   188 		{
       
   189 		TCalTime entryNextTime;
       
   190 		entryNextTime.SetTimeUtcL(TCalTime::MaxTime());
       
   191 		
       
   192 		CAgnRptDef* thisEntryRptDef = iCalLiteEntries[i]->LiteEntry().RptDef();
       
   193 		if (thisEntryRptDef)
       
   194 			{
       
   195 			TTime entryNextTimeUtc;
       
   196 			TBool instanceFound(EFalse);
       
   197 			TTime fromTimeUtc(iCurrentIndexTime.TimeUtcL() + TTimeIntervalMicroSeconds(1));
       
   198 			
       
   199 			do
       
   200 				{
       
   201 				// keep looping until we find an unexcepted instance or there are no more instances
       
   202 				instanceFound = thisEntryRptDef->NudgeNextInstanceUtcL(fromTimeUtc, entryNextTimeUtc);
       
   203 				fromTimeUtc = entryNextTimeUtc + TTimeIntervalMicroSeconds(1);
       
   204 				}
       
   205 			while (instanceFound && !thisEntryRptDef->IsAnUnexceptedInstanceL(AgnDateTime::ConvertToLocalTimeL(entryNextTimeUtc) ) );
       
   206 			
       
   207 			if (instanceFound)
       
   208 				{
       
   209 				entryNextTime.SetTimeUtcL(entryNextTimeUtc);
       
   210 				}
       
   211 			}
       
   212 		else
       
   213 			{
       
   214 			TCalTime entryInstanceTime = NonRptEntryInstanceTimeL(iCalLiteEntries[i]->LiteEntry());
       
   215 						
       
   216 			if (entryInstanceTime.TimeUtcL() > iCurrentIndexTime.TimeUtcL())
       
   217 				{
       
   218 				// The entry's instance time is after the current index time
       
   219 				// so it is a valid possible next instance
       
   220 				entryNextTime = entryInstanceTime;
       
   221 				}
       
   222 			}
       
   223 		
       
   224 		if (entryNextTime.TimeUtcL() < bestSoFar.TimeUtcL()) 
       
   225 			{
       
   226 			// This time is better than best time so far so update the best so far
       
   227 			bestSoFar = entryNextTime;
       
   228 			thisAgnSimpleEntryIndex = i;
       
   229 			iEntryWithSameTime.Reset();
       
   230 			iCurrentIndex = -1;
       
   231 			}
       
   232 		else if (entryNextTime.TimeUtcL() == bestSoFar.TimeUtcL() && entryNextTime.TimeUtcL()!= TCalTime::MaxTime())
       
   233 			{
       
   234 			//Store the index of the entry which has the instance time as the "bestSoFar" time
       
   235 			iEntryWithSameTime.AppendL(i);
       
   236 			}
       
   237 		}
       
   238 	
       
   239 	
       
   240 	if (bestSoFar.TimeUtcL() != TCalTime::MaxTime())
       
   241 		{
       
   242 		retInstance = iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[thisAgnSimpleEntryIndex], bestSoFar);
       
   243 		iCurrentIndexTime = bestSoFar;
       
   244 		}
       
   245 	
       
   246 	return retInstance;
       
   247 	}
       
   248 
       
   249 /** Returns the previous instance
       
   250 
       
   251 Loops through all the entries in the cached entry list and finds
       
   252 the latest instance that appears before the current index instance time.
       
   253 
       
   254 @return The previous instance
       
   255 
       
   256 @internalComponent
       
   257 */
       
   258 CCalInstance* CCalInstanceIteratorUid::PreviousL()
       
   259 	{
       
   260 	CCalInstance* retInstance = NULL;
       
   261 	TInt numOfsameTimeInstance = iEntryWithSameTime.Count();
       
   262 	if(numOfsameTimeInstance > 0 && iCurrentIndex >= 1)
       
   263 		{
       
   264 		// we should return the last instance in the array to make it consistent with NextL which returns the first entry's instance.
       
   265 		return iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[iEntryWithSameTime[--iCurrentIndex]], iCurrentIndexTime);
       
   266 		}
       
   267 
       
   268 	TCalTime bestSoFar;
       
   269 	bestSoFar.SetTimeUtcL(TCalTime::MinTime());
       
   270 	TInt thisAgnSimpleEntryIndex(KErrNotFound);
       
   271 	
       
   272 	const TInt KEntryCount(iCalLiteEntries.Count());
       
   273 	TInt i(0);
       
   274 	for (; i < KEntryCount ; ++i)
       
   275 		{
       
   276 		TCalTime entryPreviousTime;
       
   277 		entryPreviousTime.SetTimeUtcL(TCalTime::MinTime());
       
   278 		
       
   279 		CAgnRptDef* thisEntryRptDef = iCalLiteEntries[i]->LiteEntry().RptDef();
       
   280 		
       
   281 		if (thisEntryRptDef)
       
   282 			{
       
   283 			TTime entryPreviousTimeUtc(iCurrentIndexTime.TimeUtcL());
       
   284 			TBool instancefound(EFalse);
       
   285 			TTime fromTimeUtc;
       
   286 			
       
   287 			do
       
   288 				{
       
   289 				fromTimeUtc = entryPreviousTimeUtc - TTimeIntervalMicroSeconds(1);
       
   290 				// keep calling until an unexcepted instance is found or there are no more instances
       
   291 				instancefound = thisEntryRptDef->NudgePreviousInstanceUtcL(fromTimeUtc, entryPreviousTimeUtc);
       
   292 				}
       
   293 			while (instancefound && !thisEntryRptDef->IsAnUnexceptedInstanceL(AgnDateTime::ConvertToLocalTimeL(entryPreviousTimeUtc) ) );
       
   294 			
       
   295 			if (instancefound)
       
   296 				{
       
   297 				entryPreviousTime.SetTimeUtcL(entryPreviousTimeUtc);
       
   298 				}
       
   299 			}
       
   300 		else
       
   301 			{
       
   302 			// The entry does not have a repeat rule so it is just a single instance
       
   303 			TCalTime entryInstanceTime = NonRptEntryInstanceTimeL(iCalLiteEntries[i]->LiteEntry());
       
   304 			
       
   305 			if (entryInstanceTime.TimeUtcL() < iCurrentIndexTime.TimeUtcL())
       
   306 				{
       
   307 				// The entry's instance time is before the current index time
       
   308 				// so it is a valid possible next instance
       
   309 				entryPreviousTime = entryInstanceTime;
       
   310 				}
       
   311 			}
       
   312 		
       
   313 		if (entryPreviousTime.TimeUtcL() > bestSoFar.TimeUtcL()) 
       
   314 			{
       
   315 			// This time is better than best time so far so update the best so far
       
   316 			bestSoFar = entryPreviousTime;
       
   317 			thisAgnSimpleEntryIndex = i;
       
   318 			iEntryWithSameTime.Reset();
       
   319 			iCurrentIndex = -1;
       
   320 			}
       
   321 		else if (entryPreviousTime.TimeUtcL() == bestSoFar.TimeUtcL() && entryPreviousTime.TimeUtcL()!= TCalTime::MinTime())
       
   322 			{
       
   323 			iEntryWithSameTime.AppendL(thisAgnSimpleEntryIndex);
       
   324 			thisAgnSimpleEntryIndex = i;
       
   325 			}
       
   326 		}
       
   327 	
       
   328 	if (bestSoFar.TimeUtcL() != TCalTime::MinTime())
       
   329 		{
       
   330 		retInstance = iInstanceViewImpl.CreateInstanceL(*iCalLiteEntries[thisAgnSimpleEntryIndex], bestSoFar);
       
   331 		iCurrentIndexTime = bestSoFar;
       
   332 		numOfsameTimeInstance = iEntryWithSameTime.Count();
       
   333 		if(numOfsameTimeInstance>0)
       
   334 			{
       
   335 			iCurrentIndex = numOfsameTimeInstance;
       
   336 			}
       
   337 		}
       
   338 		
       
   339 	return retInstance;
       
   340 	}
       
   341 
       
   342 /** To check if there are more instance to be returned by NextL().
       
   343 
       
   344 Calls NextL() to see if if returns another instance, and then sets the current
       
   345 indexed instance time back to what it was before the call. 
       
   346 
       
   347 @return ETrue if there are more instance to be returned by NextL(),
       
   348 EFalse if there are no more instance, and EFalse if there is a problem
       
   349 calculating if there are more instance to be returned by NextL().
       
   350 
       
   351 @internalComponent
       
   352 */
       
   353 TBool CCalInstanceIteratorUid::HasMore() const
       
   354 	{
       
   355 	TBool returnValue(EFalse);
       
   356 	TRAP_IGNORE(returnValue = HasMoreL());
       
   357 	return returnValue;
       
   358 	}
       
   359 
       
   360 TBool CCalInstanceIteratorUid::HasMoreL() const
       
   361 	{
       
   362 	TBool returnValue(EFalse);
       
   363 
       
   364 	//Store the current state
       
   365 	TCalTime storedCurrentIndex = iCurrentIndexTime;
       
   366 	TInt storedArrayIndex = iCurrentIndex;
       
   367 	RArray<TInt> storedArray;
       
   368 	CleanupClosePushL(storedArray);
       
   369 	const TInt count = iEntryWithSameTime.Count();
       
   370 	for(TInt ii=0; ii<count;++ii)
       
   371 		{
       
   372 		storedArray.AppendL(iEntryWithSameTime[ii]);
       
   373 		}
       
   374 
       
   375 	//Find instances
       
   376 	CCalInstance* nextInstance = const_cast<CCalInstanceIteratorUid*>(this)->NextL();
       
   377 	returnValue = (nextInstance != NULL);
       
   378 	delete nextInstance;
       
   379 
       
   380 	// restore the state
       
   381 	const_cast<CCalInstanceIteratorUid*>(this)->iCurrentIndexTime = storedCurrentIndex; 
       
   382 	iCurrentIndex = storedArrayIndex;//reset index since it could be moved in NextL
       
   383 	iEntryWithSameTime.Reset();
       
   384 	const TInt countSortedArray = storedArray.Count();
       
   385 	for(TInt ii=0; ii<countSortedArray;++ii)
       
   386 		{
       
   387 		iEntryWithSameTime.AppendL(storedArray[ii]);
       
   388 		}
       
   389 
       
   390 	CleanupStack::PopAndDestroy(&storedArray);
       
   391 
       
   392 	return returnValue;
       
   393 	}
       
   394 
       
   395 /** Instance iterator count
       
   396 
       
   397 Loops through all the entries in the cached entry list and finds each of the instance counts.
       
   398 The instance count is the sum of all the entries instances.
       
   399 
       
   400 @return The sum of the instance counts for all the entries in the cached list. 
       
   401 
       
   402 @internalComponent
       
   403 */
       
   404 TInt CCalInstanceIteratorUid::Count() const
       
   405 	{
       
   406 	TInt returnInstanceCount(0);
       
   407 	const TInt KEntryCount(iCalLiteEntries.Count());
       
   408 	for (TInt i(0) ; i < KEntryCount ; ++i)
       
   409 		{
       
   410 		CAgnRptDef* rptDef = iCalLiteEntries[i]->LiteEntry().RptDef();
       
   411 		if (rptDef)
       
   412 			{
       
   413 			// This gets all the instances generated by the repeat rule
       
   414 			TRAPD(error, returnInstanceCount += rptDef->InstanceCountL());
       
   415 			if (error)
       
   416 				{
       
   417 				// an error has occoured whilst calculating the instance count
       
   418 				// so quit and retrun the error code
       
   419 				returnInstanceCount = error;
       
   420 				break;
       
   421 				}
       
   422 			
       
   423 			// Need to take off valid exception dates
       
   424 			if (rptDef->Exceptions())
       
   425 				{
       
   426 				returnInstanceCount -= rptDef->Exceptions()->Count();
       
   427 				}
       
   428 			}
       
   429 		else
       
   430 			{
       
   431 			// The entry does not have a repeat rule
       
   432 			// so it is just a single instance
       
   433 			++returnInstanceCount;	
       
   434 			}
       
   435 		}
       
   436 	
       
   437 	return returnInstanceCount;
       
   438 	}
       
   439 
       
   440