pimappservices/calendar/shared/src/agmentry.cpp
changeset 0 f979ecb2b13e
child 18 c198609911f9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pimappservices/calendar/shared/src/agmentry.cpp	Tue Feb 02 10:12:19 2010 +0200
@@ -0,0 +1,2088 @@
+// Copyright (c) 1997-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 "agmentry.h"
+
+#include "agmattendee.h"
+#include "agmcategory.h"
+#include <calinterimapipanic.h>
+#include "agmcontent.h"
+#include "agmattachment.h"
+#include "agmdate.h"
+#include "agmrptdef.h"
+#include "agmutil.h"
+
+#include <calentry.h>
+//#include "calentryimpl.h"
+#include <e32math.h>
+
+#include <asshddefs.h>
+
+
+//---------------------------------- CAgnEntry ------------------------------------------
+
+EXPORT_C CAgnEntry* CAgnEntry::NewL(CCalEntry::TType aType)
+	{
+	__ASSERT_ALWAYS(aType>=CCalEntry::EAppt && aType<=CCalEntry::EAnniv, Panic(EAgmErrBadTypeEntry));
+	// allocate a CAgnEntry object, which invokes the CAgnSimpleEntry new operator, but passing no allocator
+	// this makes the CAgnSimpleEntry new operator use the default new operator
+	
+	return new (ELeave, NULL) CAgnEntry(aType);;
+	}
+
+EXPORT_C CAgnEntry* CAgnEntry::NewL(RReadStream& aStream)
+//Creates an entry and restores it from aStream
+	{
+	// type must be read first because NewL requires it
+	TUint8 typeData = aStream.ReadUint8L();
+		
+	CCalEntry::TType type=CCalEntry::TType(typeData);
+	
+	__ASSERT_ALWAYS(type==CCalEntry::EAppt || type==CCalEntry::EEvent ||
+					type==CCalEntry::EAnniv || type==CCalEntry::ETodo ||
+					type==CCalEntry::EReminder, User::Leave(KErrCorrupt));
+
+	CAgnEntry* entry = CAgnEntry::NewL(type);
+	CleanupStack::PushL(entry);
+	entry->InternalizeL(aStream);
+	CleanupStack::Pop();
+	return entry;
+	}
+		
+
+CAgnEntry::CAgnEntry(CCalEntry::TType aType) : CAgnSimpleEntry(aType)
+	{
+	iSummary = NULL;
+	iSummaryStreamId = KNullStreamId;
+	iDescription = NULL;
+	iDescriptionStreamId = KNullStreamId;
+	SetFlagOff(EAgnAlarmActionDeleted);
+	iDTStampUtc = Time::NullTTime();
+	iLatitude=KGEODefaultValue;
+	iLongitude=KGEODefaultValue;
+	}
+
+void CAgnEntry::ConstructL(HBufC8* aUid, CCalEntry::TMethod aMethod, TUint aSeqNum)
+	{
+	iGsData = CGsParentData::NewL(aUid, aSeqNum, aMethod); // takes ownership of aUid
+	}
+
+void CAgnEntry::ConstructL(HBufC8* aUid, CCalEntry::TMethod aMethod, TUint aSeqNum, const TAgnCalendarTime& aRecurrenceId, CalCommon::TRecurrenceRange aRange)
+	{
+	iGsData = CGsChildData::NewL(aUid, aSeqNum, aMethod, aRecurrenceId, aRange); // takes ownership of aUid
+	}
+
+EXPORT_C CAgnEntry* CAgnEntry::NewL(CCalEntry::TType aType, HBufC8* aUid, CCalEntry::TMethod aMethod, TUint aSeqNum, const TAgnCalendarTime& aRecurrenceId, CalCommon::TRecurrenceRange aRange)
+	{
+	CAgnEntry* entry = new (ELeave, NULL) CAgnEntry(aType);
+	
+	CleanupStack::PushL(entry);
+	entry->ConstructL(aUid, aMethod, aSeqNum, aRecurrenceId, aRange);
+	CleanupStack::Pop(entry);
+	
+	return entry;
+	}
+
+EXPORT_C CAgnEntry* CAgnEntry::NewL(CCalEntry::TType aType, HBufC8* aUid, CCalEntry::TMethod aMethod, TUint aSeqNum)
+	{
+	CAgnEntry* entry = new (ELeave, NULL) CAgnEntry(aType);
+	
+	CleanupStack::PushL(entry);
+	entry->ConstructL(aUid, aMethod, aSeqNum);
+	CleanupStack::Pop(entry);
+	
+	return entry;
+	}
+	
+EXPORT_C CAgnEntry::~CAgnEntry()
+/** The destructor frees all resources owned by the entry, prior to its destruction. 
+@internalComponent
+*/
+	{
+	if ( iAttendeeList )
+		{
+		iAttendeeList->ResetAndDestroy();
+		delete iAttendeeList;
+		}
+	delete iMeetingOrganizer;
+	
+	delete iLocation;
+	
+	if ( iCategoryList )
+		{
+		iCategoryList->ResetAndDestroy();
+		delete iCategoryList;
+		}		
+	
+	if (iAttachments)
+		{
+		iAttachments->ResetAndDestroy();
+		delete iAttachments;		
+		}
+
+	delete iDescription;
+	delete iSummary;
+	delete iAlarmSoundName;
+	delete iAlarmAction;	
+	
+    delete iGsData;
+	}
+
+
+EXPORT_C const TDesC& CAgnEntry::Summary() const
+/** Gets a pointer to the rich text object owned by the entry.
+
+@internalComponent
+@return Pointer to the rich text object. The caller does not take ownership. */
+	{
+	if ( iSummary )
+		{
+		return *iSummary;
+		}
+		
+	return KNullDesC;
+	}
+
+
+EXPORT_C TBool CAgnEntry::CompareL(const CAgnEntry& aEntry) const
+/** Compares another entry for equality with this one.
+
+The entries' instance IDs and unique IDs are also compared.
+
+@internalComponent
+@param aEntry Pointer to an entry.
+@param aCompareId This argument is used internally, for test purposes only. 
+As it has a default value, it can be ignored by developers.
+@return ETrue if aEntry is the same as this entry, EFalse if not. Note. Replication 
+data is not included in the comparison, except for the replication status. 
+*/
+	{
+	if ( ! (*this == aEntry) )
+		{
+		return EFalse;
+		}
+
+	if ( ReplicationStatus() != aEntry.ReplicationStatus() )
+		{
+		return EFalse;
+		}
+
+	if ( HasAlarm() )
+		{
+		if ( AlarmSoundName() != aEntry.AlarmSoundName() )
+			{
+			return EFalse;
+			}
+			
+		CAgnContent* content1 = AlarmAction();
+		CAgnContent* content2 = aEntry.AlarmAction();
+		if ( content1 == NULL )
+			{
+			if ( content2 != NULL )
+				{
+				return EFalse;
+				}
+			}
+		else
+			{
+			if ( content2 == NULL )
+				{
+				return EFalse;
+				}
+				
+			if ( content1->Type() != content2->Type() )
+				{
+				return EFalse;
+				}
+				
+			if ( content1->Content() != content2->Content() )
+				{
+				return EFalse;
+				}
+				
+			if ( content1->MimeType() != content2->MimeType() )
+				{
+				return EFalse;
+				}
+			}
+		}
+	
+	if ( BusyStatus() != aEntry.BusyStatus() )
+		{
+		return EFalse;
+		}
+	
+	// Compare GEO values
+	TReal entryLatitude;
+	TReal entryLongitude;
+	
+	aEntry.GeoValue(entryLatitude,entryLongitude);
+	
+	if ( iLatitude != entryLatitude || entryLongitude != iLongitude )
+		{
+		return EFalse;
+		}	
+		
+	// Compare the user integer.
+	if (UserInt() != aEntry.UserInt())
+	    {
+	    return EFalse;
+	    }	
+	
+	if ( DTStampUtcL() != aEntry.DTStampUtcL() )
+		{
+		return EFalse;
+		}
+
+	if ( Method() != aEntry.Method() )
+		{
+		return EFalse;
+		}
+
+	if ( SequenceNumber() != aEntry.SequenceNumber() )
+		{
+		return EFalse;
+		}
+	
+	if ( RecurrenceId() != aEntry.RecurrenceId() )
+		{
+		return EFalse;
+		}
+	
+	const TInt KNumOfCategories = CategoryCount();
+	
+	if ( aEntry.CategoryCount() != KNumOfCategories )
+		{
+		return EFalse;
+		}
+	
+	const RPointerArray<CAgnCategory>* categoryList1 = iCategoryList;
+	const RPointerArray<CAgnCategory>* categoryList2 = aEntry.iCategoryList;
+
+	if (categoryList1 && categoryList2)
+		{
+		TBool categoryFound = EFalse;
+
+		for ( TInt i = 0 ; i < KNumOfCategories; ++i )
+			{
+			categoryFound = EFalse;
+
+			for ( TInt j = 0; ! categoryFound && j < KNumOfCategories; ++j )
+				{
+				if ( (*categoryList1)[i]->Category() == (*categoryList2)[j]->Category() )
+					{
+					if ( (*categoryList1)[i]->Category() == CCalCategory::ECalExtended )
+						{
+						if ( (*categoryList1)[i]->ExtendedCategoryName() == (*categoryList2)[j]->ExtendedCategoryName() )
+							{
+							categoryFound = ETrue;
+							}
+						}
+					else
+						{
+						categoryFound = ETrue;
+						}
+					}
+				}
+
+			if ( !categoryFound )
+				{
+				return EFalse;
+				}
+			}
+		}
+
+	const TInt KNumOfAttendees = AttendeeCount();
+
+	if ( KNumOfAttendees != aEntry.AttendeeCount() )
+		{
+		return EFalse;
+		}
+
+	if ( KNumOfAttendees > 0 && KNumOfAttendees == aEntry.AttendeeCount() )
+		{
+		const RPointerArray<CAgnAttendee>& KAttendeeList1 = *iAttendeeList;
+		const RPointerArray<CAgnAttendee>& KAttendeeList2 = *aEntry.iAttendeeList;
+
+		for ( TInt i = 0; i < KNumOfAttendees; ++i )
+			{
+			const TPtrC& KAttendee1 = KAttendeeList1[i]->Address();
+
+			TBool attendeeFound = EFalse;
+			
+			for ( TInt j = 0; !attendeeFound && j < KNumOfAttendees; ++j )
+				{
+				const TPtrC& KAttendee2 = KAttendeeList2[j]->Address();
+				
+				if ( KAttendee1.CompareF(KAttendee2) == 0 )
+					{
+					attendeeFound = ETrue;
+					}
+				}
+				
+			if ( !attendeeFound )
+				{
+				return EFalse;
+				}
+			}
+		}
+
+	const TInt KNumAttachments = AttachmentCount();
+	if (KNumAttachments != aEntry.AttachmentCount())
+		{
+		return EFalse;
+		}
+	if (KNumAttachments > 0)
+		{
+		RArray<TBool> foundAttachmentAlready;
+		CleanupClosePushL(foundAttachmentAlready);
+		
+		for (TInt i = 0; i < KNumAttachments; ++i)
+			{
+			foundAttachmentAlready.AppendL(EFalse);
+			}
+		
+		for (TInt i = 0; i < KNumAttachments; ++i)
+			{
+			TBool attachmentFound = EFalse;
+			for (TInt j = 0; j < KNumAttachments; ++j)
+				{
+				if (!foundAttachmentAlready[j] && Attachment(i).CompareL(aEntry.Attachment(j)))
+					{
+					foundAttachmentAlready[j] = ETrue;
+					attachmentFound = ETrue;
+					break;
+					}
+				}
+			if (!attachmentFound)
+				{
+				CleanupStack::PopAndDestroy(); // foundAttachmentAlready.Close()
+				return EFalse;
+				}
+			}
+		
+		CleanupStack::PopAndDestroy(); // foundAttachmentAlready.Close()
+		}
+	
+	if ( PhoneOwner() == NULL )
+		{
+		if ( aEntry.PhoneOwner() != NULL )
+			{
+			return EFalse;
+			}
+		}
+	else
+		{
+		// PhoneOwner() != NULL
+		if ( aEntry.PhoneOwner() == NULL )
+			{
+			return EFalse;
+			}
+		else if ( PhoneOwner()->Address() != aEntry.PhoneOwner()->Address() )
+			{
+			return EFalse;
+			}
+		}
+
+	if ( Summary() != aEntry.Summary() )
+		{
+		return EFalse;
+		}
+
+	if ( Description() != aEntry.Description() )
+		{
+		return EFalse;
+		}
+
+	if ( Location() != aEntry.Location() )
+		{
+		return EFalse;
+		}
+	
+	return ETrue;
+	}
+
+
+EXPORT_C const TDesC& CAgnEntry::AlarmSoundName() const
+/** Gets the name of the alarm sound as set by SetAlarmSoundName(). 
+
+Returns NULL if the entry isn't alarmed.
+
+@internalComponent
+@return The name of the alarm sound. 
+*/
+	{
+
+	if ( HasAlarm() && iAlarmSoundName )
+		{
+		return *iAlarmSoundName;
+		}		
+	
+	return KNullDesC();
+	}
+
+
+EXPORT_C void CAgnEntry::SetAlarmSoundNameL(const TDesC& aAlarmSoundName)
+/** Sets the name of the alarm sound.
+
+Note: if the length of the new alarm sound name is greater than KMaxAlarmSoundName 
+characters, it will be ignored.
+
+@internalComponent
+@param aAlarmSoundName The name of the alarm sound. 
+*/
+	{
+	const TInt KLen = aAlarmSoundName.Length();
+	
+	if ( KLen > 0 && KLen <= KMaxAlarmSoundNameLength )
+		{
+		// delete and set always to NULL before AllocL because
+		// that call could leave and the pointer be not NULL
+				
+		delete iAlarmSoundName;
+		iAlarmSoundName = NULL;
+			
+		iAlarmSoundName = aAlarmSoundName.AllocL();
+		}
+	}
+
+
+EXPORT_C void CAgnEntry::ClearAlarm()
+/** Clear associated alarm
+
+@internalComponent
+*/
+	{
+	delete iAlarmSoundName;
+	iAlarmSoundName = NULL;
+		
+	if ( iAlarmActionStreamId != KNullStreamId)
+		{
+		SetFlagOn(EAgnAlarmActionDeleted);
+		}
+	
+    delete iAlarmAction;
+    iAlarmAction = NULL;
+		
+	SetAlarmOffset(KAlarmNotSet);
+	}
+
+ void CAgnEntry::ExternalizeGsDataL(RWriteStream& aStream, TBool aToBuffer) const
+	{
+	aStream.WriteInt8L(GsDataType());
+	
+	if(aToBuffer)
+		{
+		iGsData->ExternalizeToBufferL(aStream);		
+		}
+	else
+		{
+		iGsData->ExternalizeL(aStream);	
+		}
+	}
+ 
+EXPORT_C void CAgnEntry::PruneRDatesL(const TAgnCalendarTime& aRecurrenceId, CalCommon::TRecurrenceRange aRange)
+/**
+Used when adding a repeating child to a parent entry.
+Removes all sporadic dates either after or before the specified recurrence ID. 
+@internalComponent
+*/
+	{
+	__ASSERT_DEBUG(iGsData->GsDataType() == CGsData::EParent, Panic(EAgmErrNotParentEntry));
+	__ASSERT_DEBUG(RptDef(), Panic(EAgmErrNotParentEntry));
+	__ASSERT_DEBUG(aRange == CalCommon::EThisAndFuture || aRange == CalCommon::EThisAndPrior, Panic(EAgmErrInvalidRecurrenceRange));
+	
+	if (RptDef()->HasSporadicDates())
+		{
+		const RArray<TAgnCalendarTime>* KSporadicDates = RptDef()->SporadicDateList();
+		
+		for (TInt i = KSporadicDates->Count() - 1; i >= 0; --i)
+			{
+			const TAgnCalendarTime& KSporadicDate = (*KSporadicDates)[i];
+			if ( (aRecurrenceId > KSporadicDate && aRange == CalCommon::EThisAndPrior ) ||
+				 (aRecurrenceId < KSporadicDate && aRange == CalCommon::EThisAndFuture ) )
+				{
+				RptDef()->RemoveSporadicDate(KSporadicDate);
+				}
+			}
+		}
+	}
+
+void CAgnEntry::InternalizeGsDataL(RReadStream& aStream, TBool aFromBuffer)
+ 	{
+ 	CGsData::TGsDataType dataType =  static_cast<CGsData::TGsDataType>(aStream.ReadInt8L());
+	
+	if(dataType == CGsData::EParent)
+		{
+		iGsData = CGsParentData::NewL();
+		}
+	else 
+		{
+		iGsData = CGsChildData::NewL();
+		}
+		
+	if(aFromBuffer)
+		{
+		iGsData->InternalizeFromBufferL(aStream);
+		}
+	else
+		{
+		iGsData->InternalizeL(aStream);
+		}
+  	}
+	
+EXPORT_C void CAgnEntry::ExternalizeL(RWriteStream& aStream) const
+/** Externalises an entry's details and attributes, but not its rich text to a 
+write stream. 
+
+The presence of this function means that the standard templated operator<<() 
+(defined in s32strm.h) is available to externalise objects of this class.
+
+@internalComponent
+@param aStream Stream to which the object should be externalised. 
+*/
+	{
+	ExternalizeEntryL(aStream);
+	ExternalizeGsDataL(aStream, EFalse);
+	}
+
+void CAgnEntry::ExternalizeEntryL(RWriteStream& aStream, TBool aToBuffer) const
+	{
+	CAgnSimpleEntry::doExternalizeL(aStream, aToBuffer);
+	aStream.WriteInt8L(iReplicationStatus);
+	
+	if ( HasAlarm() )
+		{
+		if (iAlarmSoundName)
+			{
+			aStream << *iAlarmSoundName;
+			}			
+		else
+			{
+			aStream << KNullDesC();
+			}		
+		}
+
+	// Make sure there is no server pointer
+	// - This may have been set up from a previous FetchEntry
+	__ASSERT_DEBUG(iSummaryStreamId == KNullStreamId ||
+			    !(iSummary && iSummary->Length() > 0 && iSummaryStreamId == KNullStreamId),
+				 Panic(EAgmNoNotesStreamId));
+
+	aStream << iSummaryStreamId;
+
+	TInt size = 0;
+	if ( iLocation )
+		{
+		size = iLocation->Length();
+		aStream.WriteUint32L(size);
+		aStream.WriteL(iLocation->Des(), size);
+		}
+	else
+		{
+		size = 0;
+		aStream.WriteUint32L(size);
+		}
+
+	TInt phoneOwnerIndex = 0;
+	
+	if ( iAttendeeList )
+		{
+		size = iAttendeeList->Count();
+		aStream.WriteUint32L(size);
+		
+		for ( TInt i = 0; i < size; ++i )
+			{
+			CAgnAttendee*& attendeeI = (*iAttendeeList)[i];			
+			
+			attendeeI->ExternalizeL(aStream);
+			
+			if ( iPhoneOwner == attendeeI )
+				{
+				phoneOwnerIndex = i + 1;
+				}
+			}
+		}
+	else
+		{		
+		size = 0;
+		aStream.WriteUint32L(size);
+		}
+
+	//	phone owner index. 0 implies no phoneowner
+	aStream.WriteUint32L(phoneOwnerIndex);
+
+	//	meeting organizer if present
+	if (iMeetingOrganizer)
+		{
+		aStream.WriteUint8L(ETrue);
+		iMeetingOrganizer->ExternalizeL(aStream);
+		}
+	else
+		{
+		aStream.WriteUint8L(EFalse);
+		}
+		
+	// Write the creation date field
+
+	aStream << iDTStampUtc.Int64();
+
+	// this does not change the file format
+	if ( iCategoryList )
+		{
+		size = iCategoryList->Count();
+		aStream.WriteUint32L(size);
+		
+		for ( TInt ccount = 0; ccount < size; ++ccount )
+			{
+			(*iCategoryList)[ccount]->ExternalizeL(aStream);
+			}
+		}
+	else
+		{		
+		size = 0;
+		aStream.WriteUint32L(size);
+		}
+	
+	// Write the Notes Stream Id - Null value indicates no Notes data.
+	// If the Notes exist, they should have been saved previously, so Stream id != 0 !!!
+	__ASSERT_DEBUG((iDescriptionStreamId == KNullStreamId) ||
+				    !(iDescription && iDescription->Length() > 0 && iDescriptionStreamId == KNullStreamId),
+					 Panic(EAgmNoNotesStreamId));
+	aStream << iDescriptionStreamId;
+	aStream << iAlarmActionStreamId;
+
+	aStream.WriteUint8L(iBusyStatus);
+	
+	// GEO properties
+	aStream.WriteReal64L(iLatitude);
+	aStream.WriteReal64L(iLongitude);
+	
+	const TInt KAttachmentCount = AttachmentCount();
+	aStream.WriteUint16L(KAttachmentCount);
+	for (TInt i = 0; i < KAttachmentCount; ++i)
+		{
+		if ( ! Attachment(i).FlagsSet(CAgnAttachment::EDataHasBeenSet))
+			{
+			// attachments with just content IDs should not be stored
+			User::Leave(KErrArgument);
+			}
+		else
+			{
+			aStream << Attachment(i);
+			}
+		}
+
+    // Set the user integer of the stream.
+	aStream.WriteInt32L( UserInt() );
+	
+	// future DC proofing
+	aStream.WriteUint32L(0); // number of bytes until end of entry
+	}
+
+
+EXPORT_C void CAgnEntry::InternalizeL(RReadStream& aStream)
+	{
+	InternalizeEntryL(aStream, EFalse);
+	InternalizeGsDataL(aStream, EFalse);
+	}
+
+void CAgnEntry::InternalizeEntryL(RReadStream& aStream, TBool aFromBuffer)
+/** Internalises an entry's details and attributes, but not its rich text from 
+a read stream. 
+
+The presence of this function means that the standard templated operator>>() 
+(defined in s32strm.h) is available to internalise objects of this class.
+
+@internalComponent
+@param aStream Stream from which the object should be internalised. 
+*/
+	{
+	CAgnSimpleEntry::doInternalizeL(aStream, aFromBuffer);
+	iReplicationStatus = static_cast<CCalEntry::TReplicationStatus>(aStream.ReadInt8L());
+	
+	delete iAlarmSoundName;
+	iAlarmSoundName = NULL;
+	
+	if ( HasAlarm() )
+		{
+		iAlarmSoundName = HBufC::NewL(aStream, KMaxAlarmSoundNameLength);
+		if ( iAlarmSoundName->Length() == 0 )
+			{
+			delete iAlarmSoundName;
+			iAlarmSoundName = NULL;
+			}
+		}
+
+	aStream >> iSummaryStreamId;
+
+	// Delete any location that may exist
+	delete iLocation;
+	iLocation = NULL;
+
+	TInt size = aStream.ReadUint32L();
+	if ( size )
+		{
+		iLocation = HBufC::NewL(size);
+		TPtr bufPtr = iLocation->Des();
+		aStream.ReadL(bufPtr, size);
+		}
+
+	size = aStream.ReadUint32L();
+	if ( iAttendeeList )
+		{
+		iAttendeeList->ResetAndDestroy();
+		}
+	else
+		{
+		if ( size )
+			{
+			CreateAttendeeListL();
+			}
+		}
+	iPhoneOwner = NULL;
+	iMeetingOrganizer = NULL;
+	
+	for ( TInt count = 0; count < size; ++count )
+		{
+		CAgnAttendee* attendee = CAgnAttendee::NewL(aStream);
+		CleanupStack::PushL(attendee);
+		iAttendeeList->AppendL(attendee);
+		CleanupStack::Pop(attendee);
+		}
+		
+	// populate the phoneowner/organizer fields if existing
+	TInt phoneOwnerIndex = aStream.ReadUint32L();
+	if (phoneOwnerIndex > 0)
+		{
+		iPhoneOwner = (*iAttendeeList)[phoneOwnerIndex-1];
+		}
+
+	//	meeting organizer if present
+	if (aStream.ReadUint8L())
+		{
+		iMeetingOrganizer = CAgnAttendee::NewL(aStream);
+		}
+	
+	TInt64 dtStamp;
+	aStream >> dtStamp;
+	iDTStampUtc = dtStamp;
+
+	size = aStream.ReadUint32L();
+	
+	if ( iCategoryList )
+		{
+		iCategoryList->ResetAndDestroy();
+		}
+	else
+		{
+		if ( size )
+			{
+			iCategoryList = new (ELeave) RPointerArray<CAgnCategory>;
+			}
+		}
+		
+	for ( TInt ccount = 0; ccount < size; ++ccount )
+		{
+		CAgnCategory* category = CAgnCategory::NewL(aStream);
+		CleanupStack::PushL(category);
+		iCategoryList->AppendL(category);
+		CleanupStack::Pop(category);
+		}
+		
+	// If it's the new file format read in the Stream Id for the notes text
+	aStream >> iDescriptionStreamId;
+
+	aStream >> iAlarmActionStreamId;
+		
+	iBusyStatus = static_cast<CCalEntry::TTransp>(aStream.ReadUint8L());
+	
+	// GEO properties	
+	TReal geoLatitude = aStream.ReadReal64L();
+	TReal geoLongitude = aStream.ReadReal64L();
+	
+	SetGeoValueL(geoLatitude, geoLongitude);
+	
+	TInt attachmentCount = aStream.ReadUint16L();
+	for (TInt i = 0; i < attachmentCount; ++i)
+		{
+		
+		CAgnAttachment* attachment = AttachmentFactory::NewAttachmentL(aStream);
+		CleanupStack::PushL(attachment);
+		AddAttachmentL(attachment);
+		CleanupStack::Pop(attachment);
+		}
+	
+	// Set the user integer of this entry from the stream.
+	SetUserInt(aStream.ReadInt32L());
+	
+	// future DC proofing
+	size = aStream.ReadUint32L(); // number of bytes until end of entry
+	while (size > 0)
+		{
+		aStream.ReadUint8L(); // ignore data
+		size--;
+		}
+	}
+
+EXPORT_C CAgnEntry* CAgnEntry::CloneL() const
+	{
+	CAgnEntry* entry = NULL;
+	HBufC8* guid = (this->Guid()).AllocLC();
+	if(this->GsDataType() == CGsData::EParent)
+		{
+		entry = CAgnEntry::NewL(this->Type(), guid, this->Method(), this->SequenceNumber());
+		}
+	else
+		{
+		entry = CAgnEntry::NewL(this->Type(), guid, this->Method(), this->SequenceNumber(), this->RecurrenceId(), this->RecurrenceRange());
+		}
+	CleanupStack::Pop(guid);
+	CleanupStack::PushL(entry);
+	entry->CopyFromL(*this, CCalEntry::ECopyAll);
+	CleanupStack::Pop(entry);
+	return entry;
+	}
+	
+EXPORT_C void CAgnEntry::CopyFromL(const CAgnEntry& aSource, CCalEntry::TCopyType aCopyType)
+/** Copy the details common to all entry types from aSource.
+If aCopyType is EShallowCopy it indicates that if aSources rich text is stored out of line and its
+not loaded then it isn't loaded and copied
+*/
+	{
+	CopySimpleEntryL(aSource, aCopyType);
+
+	// NOTE: don't use the internal set methods with pointers because doing a CopyFrom
+	// we are supposed to carbon copy the original. If the original has a NULL
+	// pointer in a member, we have to do the same and not keep any old stuff
+	iReplicationStatus = aSource.iReplicationStatus;	
+
+	if( iAttendeeList )
+		{
+		iAttendeeList->ResetAndDestroy();
+		}
+	iPhoneOwner = NULL;
+	delete iMeetingOrganizer;
+	iMeetingOrganizer = NULL;
+
+	const TInt KAttendees = aSource.AttendeeCount();
+	for ( TInt count = 0; count < KAttendees; ++count )
+		{
+		CAgnAttendee& attendee = aSource.FetchAttendee(count);
+
+		CAgnAttendee* newAttendee = attendee.CloneL();
+		AddAttendeeL(newAttendee);
+		
+		if ( aSource.PhoneOwner() == &attendee )
+			{
+			SetPhoneOwnerL(newAttendee);
+			}
+		}
+	
+	if (aSource.Organizer())
+		{
+		iMeetingOrganizer = aSource.Organizer()->CloneL();
+		}
+
+	// Copy the Location
+	delete iLocation;
+	iLocation = NULL;
+
+	if ( aSource.iLocation )
+		{
+		iLocation = aSource.iLocation->AllocL();
+		}
+
+	iDTStampUtc = aSource.iDTStampUtc;
+	
+	if( iCategoryList )
+		{
+		iCategoryList->ResetAndDestroy();
+		}
+		
+	const TInt KCategories = aSource.CategoryCount();
+	for ( TInt ccount = 0; ccount < KCategories; ++ccount )
+		{
+		CAgnCategory& category = aSource.FetchCategory(ccount);
+
+		CAgnCategory* newCategory = CAgnCategory::NewL(category);
+		CleanupStack::PushL(newCategory);
+		AddCategoryL(newCategory);
+		CleanupStack::Pop(newCategory);
+		}
+		
+	iBusyStatus = aSource.BusyStatus();
+	
+	// GEO properties
+	TReal sourceLatitude;
+	TReal sourceLongitude;
+	aSource.GeoValue(sourceLatitude,sourceLongitude);
+	
+	iLatitude = sourceLatitude;
+	iLongitude = sourceLongitude;
+
+	// Copy the Notes buffer
+	
+	delete iDescription;
+	iDescription = NULL;
+	
+	if ( aSource.iDescription )
+		{
+		iDescription = aSource.iDescription->AllocL();
+		}
+		
+	iDescriptionStreamId = aSource.iDescriptionStreamId;
+
+
+	// Copy the Summary buffer
+
+	delete iSummary;
+	iSummary = NULL;
+
+	if ( aSource.iSummary )
+		{
+		iSummary = aSource.iSummary->AllocL();
+		}
+		
+	iSummaryStreamId = aSource.iSummaryStreamId;
+
+
+	// Copy the Alarm sound name
+
+	delete iAlarmSoundName;
+	iAlarmSoundName = NULL;
+
+	if ( aSource.iAlarmSoundName )
+		{
+		iAlarmSoundName = aSource.iAlarmSoundName->AllocL();
+		}
+
+
+	// Copy the Alarm action
+
+	delete iAlarmAction;
+	iAlarmAction = NULL;
+		
+	if ( aSource.iAlarmAction )
+		{
+		iAlarmAction = aSource.iAlarmAction->CloneL();			
+		}
+
+	iAlarmActionStreamId = aSource.iAlarmActionStreamId;
+	iFlags = aSource.iFlags;
+	
+	if ( iAttachments )
+		{
+		iAttachments->ResetAndDestroy();
+		delete iAttachments;
+		iAttachments = NULL;
+		}
+		
+	const TInt KAttachments = aSource.AttachmentCount();
+	for ( TInt i = 0; i < KAttachments; ++i )
+		{
+		CAgnAttachment& attachment = aSource.Attachment(i);
+		CAgnAttachment* attachmentCopy = AttachmentFactory::CloneL(attachment);
+		CleanupStack::PushL(attachmentCopy);
+		AddAttachmentL(attachmentCopy);
+		CleanupStack::Pop(attachmentCopy);
+		}
+
+	iGsData->CopyDataL(*aSource.iGsData);
+	
+	if(aCopyType == CCalEntry::ECopyAll)
+		{
+		HBufC8* guid = aSource.Guid().AllocL();
+		SetGuid(guid);
+		}		
+	}
+	
+EXPORT_C CCalEntry::TReplicationStatus CAgnEntry::ReplicationStatus() const
+/** Get ReplicationStatus
+
+@internalComponent
+*/
+	{
+	return static_cast<CCalEntry::TReplicationStatus>(iReplicationStatus);
+	}
+
+
+EXPORT_C void CAgnEntry::SetReplicationStatusL(CCalEntry::TReplicationStatus aReplicationStatus)
+/** Set ReplicationStatus
+
+@internalComponent
+@leave KErrArgument if passed parameter exceeds boundaries
+*/
+	{
+	if( aReplicationStatus < CCalEntry::EOpen || aReplicationStatus > CCalEntry::ERestricted )
+		{
+		User::Leave(KErrArgument);
+		}
+	
+	iReplicationStatus = aReplicationStatus;
+	}
+
+
+EXPORT_C TBool CAgnEntry::SummaryIsLoaded() const
+/** Check if summary text is loaded from stream
+
+@internalComponent
+*/
+	{
+	if ( ! iSummary && iSummaryStreamId != KNullStreamId )
+		{
+		return EFalse;
+		}		
+
+	return ETrue;
+	}
+
+
+EXPORT_C void CAgnEntry::SetSummary(HBufC* aSummary)
+/** Set summary
+
+@internalComponent
+*/
+	{
+	delete iSummary;
+	iSummary = aSummary;
+	}
+
+
+EXPORT_C void CAgnEntry::SetLocationL(const TDesC& aLocation)
+/** Sets the contents of the entry's location field. 
+
+Sets the entry's 'has extended' property.
+
+@internalComponent
+@param aLocation Descriptor containing a location, e.g. for a meeting. 
+*/
+	{
+	delete iLocation;
+	iLocation = NULL;
+	iLocation = aLocation.AllocL();
+	}
+
+
+EXPORT_C const TDesC& CAgnEntry::Location() const
+/** Gets the contents of the entry's location field.
+
+@internalComponent
+@return The location field. NULL if the entry has no location field. 
+*/
+	{
+	if ( iLocation )
+		{
+		return *iLocation;
+		}
+		
+	return KNullDesC();
+	}
+
+
+EXPORT_C TInt CAgnEntry::AttendeeCount() const
+/** Gets the number of attendees that have been added to the entry.
+
+@internalComponent
+@return Number of attendees added. 
+*/
+	{
+	if ( ! iAttendeeList )
+		{
+		return 0;
+		}
+	
+	return iAttendeeList->Count();
+	}
+
+EXPORT_C CAgnAttendee& CAgnEntry::FetchAttendee(TInt aIndex) const
+/** Gets the attendee at the specified index within the entry's list of 
+attendees. 
+
+The index specified must be valid (between zero and AttendeeCount() 
+- 1), otherwise a panic occurs.
+
+@internalComponent
+@param aIndex Index to identify the specified attendee.
+@return The attendee details. */
+	{
+	return *(*iAttendeeList)[aIndex];
+	}
+
+
+EXPORT_C void CAgnEntry::AddAttendeeL(CAgnAttendee* aAttendee)
+/** Appends an attendee to the entry's list of attendees.
+
+@internalComponent
+@param aAttendee Pointer to the attendee details. 
+*/
+	{
+	CleanupStack::PushL(aAttendee);
+	CreateAttendeeListL();
+	
+	// Add an attendee for this entry
+	iAttendeeList->AppendL(aAttendee);
+	CleanupStack::Pop(aAttendee);
+	}
+
+void CAgnEntry::CreateAttendeeListL()
+	{
+	if ( !iAttendeeList )
+		{
+		iAttendeeList = new (ELeave) RPointerArray<CAgnAttendee>;
+		}
+	}
+	
+EXPORT_C void CAgnEntry::SetOrganizerL(CAgnAttendee* aAttendee)
+/** Set attendee as organiser
+
+@internalComponent
+*/
+	{
+	if (iMeetingOrganizer == iPhoneOwner)
+		{
+		iPhoneOwner = NULL;
+		}
+	delete iMeetingOrganizer;
+	iMeetingOrganizer = aAttendee;
+	}
+
+EXPORT_C CAgnAttendee* CAgnEntry::Organizer() const
+/** Get Organizer as attendee object
+
+@internalComponent
+*/
+	{
+	return iMeetingOrganizer;
+	}
+
+EXPORT_C void CAgnEntry::DeleteAttendee(TInt aIndex)
+/** Deletes the attendee at the index specified from the entry's list of attendees. 
+
+If there is no attendee at the index specified, a panic occurs.
+
+@internalComponent
+@param aIndex Index of the attendee to delete. 
+*/
+	{
+	CAgnAttendee* attendee = (*iAttendeeList)[aIndex];
+	
+	if (iPhoneOwner == attendee)
+		{
+		iPhoneOwner = NULL;
+		}
+		
+	if (iMeetingOrganizer == attendee)
+		{
+		iMeetingOrganizer = NULL;
+		}
+		
+	iAttendeeList->Remove(aIndex);
+	delete attendee;
+	}
+
+
+EXPORT_C CAgnAttendee* CAgnEntry::PhoneOwner() const
+/** Get Phone owner as attendee object
+
+@internalComponent
+*/
+	{
+	return iPhoneOwner;
+	}
+
+
+EXPORT_C void CAgnEntry::SetPhoneOwnerL(CAgnAttendee* aAttendee)
+/** Set Phone owner as attendee, this must be an existing attendee
+
+@internalComponent
+@leave KErrNotFound if the passed attendee is not matching anyone in the current list
+*/
+	{
+	TInt ownerExists = KErrNotFound;
+	
+	if (iAttendeeList)
+		{
+		const TInt KCount = iAttendeeList->Count();
+		
+		for (TInt i = 0; i < KCount; ++i)
+			{		
+			if (aAttendee == (*iAttendeeList)[i])
+				{
+				ownerExists = i;
+				}
+			}
+		}
+		
+	if (ownerExists == KErrNotFound && aAttendee != iMeetingOrganizer)	
+		{
+		User::Leave(KErrNotFound);
+		}
+		
+	iPhoneOwner = aAttendee;
+	}
+
+
+EXPORT_C void CAgnEntry::SetDTStampUtcL(const TTime& aDTStampUtc)
+/**
+@internalComponent
+*/
+	{
+	iDTStampUtc = aDTStampUtc;
+	}
+
+
+EXPORT_C const TTime& CAgnEntry::DTStampUtcL() const
+/**
+@internalComponent
+@return TTime
+*/
+	{
+	return iDTStampUtc;
+	}
+
+EXPORT_C TInt CAgnEntry::CategoryCount() const
+/** Gets the number of categories owned by the entry.
+
+@internalComponent
+@return The number of categories. 
+*/
+	{
+	if ( !iCategoryList )
+		{
+		return 0;
+		}
+	
+	return iCategoryList->Count();
+	}
+
+
+EXPORT_C void CAgnEntry::AddCategoryL(CAgnCategory* aCategory)
+/** Appends a category to the entry's list of categories. 
+
+The entry takes ownership of the category specified.
+
+@internalComponent
+@param aCategory The category to be added
+@leave KErrAlreadyExists if category already present
+*/
+	{
+	// Add an category for this entry
+	if ( !iCategoryList )
+		{
+		iCategoryList = new (ELeave) RPointerArray<CAgnCategory>;
+		}		
+
+	// Need to check that the category isn't already in the list
+	if ( ! CategoryExist(*aCategory) )
+		{
+		iCategoryList->AppendL(aCategory);
+		}
+	else
+		{
+		User::Leave(KErrAlreadyExists);
+		}
+	}
+
+TBool CAgnEntry::CategoryExist(CAgnCategory& aSearchCategory) const
+/** Check if category is already present
+
+@internalComponent
+*/
+	{
+	if (!iCategoryList)
+		{
+		return EFalse;
+		}
+	
+	//return ETrue if aSearchCategory belongs to this object, otherwise return EFalse
+	const TInt KNumCatList = iCategoryList->Count();
+	
+	for ( TInt i = 0; i < KNumCatList; ++i )
+		{
+		CAgnCategory& category = FetchCategory(i);
+		
+		CCalCategory::TCalCategoryType categoryType = category.Category();
+		
+		if ( categoryType == aSearchCategory.Category()) 
+			{
+			if ( categoryType == CCalCategory::ECalExtended ) // Need to compare names
+				{
+				if ( category.ExtendedCategoryName().CompareF(aSearchCategory.ExtendedCategoryName()) == 0 )
+					{
+					return ETrue;
+					}
+				}
+			else
+				{
+				return ETrue;
+				}
+			}
+		}
+
+	return EFalse;
+	}
+
+
+EXPORT_C CAgnCategory& CAgnEntry::FetchCategory(TInt aIndex) const
+/** Gets the indexed category.
+
+@internalComponent
+@param aIndex Index into the entry's list of categories. Must be valid 
+or a panic occurs.
+@return Pointer to the category located at the index specified. 
+*/
+	{
+	__ASSERT_DEBUG(iCategoryList != NULL, Panic(EAgmErrCategoryListNotInitialised));
+	__ASSERT_DEBUG(aIndex < iCategoryList->Count(), Panic(EAgmErrCategoryOutOfRange));
+	
+	return *(*iCategoryList)[aIndex];
+	}
+
+
+EXPORT_C void CAgnEntry::DeleteCategory(TInt aIndex)
+/** Deletes the indexed category.
+
+@internalComponent
+@param aIndex Index into the entry's list of categories. Must be valid 
+or a panic occurs. 
+*/
+	{
+	__ASSERT_DEBUG(iCategoryList != NULL, Panic(EAgmErrCategoryListNotInitialised));
+	CAgnCategory* category = (*iCategoryList)[aIndex];
+	delete category;
+	iCategoryList->Remove(aIndex);
+	
+	if ( iCategoryList->Count() == 0 )
+		{
+		iCategoryList->ResetAndDestroy();
+		delete iCategoryList;
+		iCategoryList=NULL;
+		}
+	}
+
+
+EXPORT_C const TDesC& CAgnEntry::Description() const
+/** Gets the notes text. 
+
+If no notes text has been set, a empty descriptor (KNullDesC) is returned.
+
+@internalComponent
+@capability ReadUserData
+@return The notes text. 
+*/
+	{
+	if ( iDescription )
+		{
+		return *iDescription;
+		}
+	return KNullDesC;
+	}
+
+
+EXPORT_C TBool CAgnEntry::DescriptionIsLoaded() const
+/** Check notes is loaded
+
+@internalComponent
+@capability ReadUserData
+@return Boolean to indicate if loaded or not
+*/
+	{
+	if ( !iDescription && iDescriptionStreamId != KNullStreamId )
+		{
+		return EFalse;
+		}		
+
+	return ETrue;
+	}
+
+
+EXPORT_C void CAgnEntry::SetDescription(HBufC* aDescription)
+/** Sets the notes text. 
+
+This object takes ownership of aNotes.
+
+@internalComponent
+@param aNotes Notes text. 
+*/
+	{
+	delete iDescription;
+	iDescription = aDescription;
+	}
+
+
+EXPORT_C CAgnEntry::TAgnDataChange CAgnEntry::DescriptionChange() const
+/** Check if the notes changed
+
+	1. If iDescription is NULL, The description has never been added  or never been loaded - No Change
+	2. If iDescriptionStreamId is not KNullStreamId and iDecription is KNullDesC, The descrioption has been deleted (CAgnEntry::SetDescrioprion() can be used to delete description)
+	3. If iDescriptionStreamId is not KNullStreamId and iDecription is not KNullDesC, The descrioption could be updated
+	4. If iDescriptionStreamId is KNullStreamId and iDescription is not KNullDesC, The description has been added
+
+@internalComponent
+@return TAgnDescriptionChange value indicating the type of change
+*/
+	{
+	TAgnDataChange change = EAgnDataNoChange;
+	if ( iDescription )
+		{
+		if ( iDescriptionStreamId != KNullStreamId )
+			{
+			if ( *iDescription == KNullDesC )
+				{
+				change = EAgnDataDeleted;
+				}
+			else
+				{
+				change = EAgnDataUpdated;
+				}
+			}
+		else if ( *iDescription != KNullDesC )
+			{
+			change = EAgnDataAdded;
+			}
+		}
+
+	return change;
+	}
+
+
+EXPORT_C CAgnEntry::TAgnDataChange CAgnEntry::SummaryChange() const
+/** Check if the summary changed
+
+	1. If iSummary is NULL, The Summary has never been added or laoded- No Change
+	2. If iSummaryStreamId is not KNullStreamId and iSummary is KNullDesC, The Summary has been deleted (CAgnEntry::SetSummary() can be used to delete description)
+	3. If iSummaryStreamId is not KNullStreamId and iSummary is not KNullDesC, The Summary could be updated
+	4. If iSummaryStreamId is KNullStreamId and iSummary is not KNullDesC, The Summary has been added
+
+@internalComponent
+@return TAgnSummaryChange value indicating the type of change
+*/
+	{
+	TAgnDataChange change = EAgnDataNoChange;
+	
+	if ( iSummary )
+		{
+		if ( iSummaryStreamId != KNullStreamId )
+			{
+			if ( *iSummary == KNullDesC )
+				{
+				change = EAgnDataDeleted;
+				}
+			else
+				{
+				change = EAgnDataUpdated;
+				}
+			}
+		else if ( *iSummary != KNullDesC )
+			{
+			change = EAgnDataAdded;
+			}
+		}
+
+	return change;
+	}
+
+
+EXPORT_C CAgnEntry::TAgnDataChange CAgnEntry::AlarmActionChange() const
+/** Check if the alarm action changed
+
+	1. If iAlarmActionDeleted is true, alarm has been deleted
+	2. If iAlarmActionStreamId is KNullStreamId and iAlarmAction is not NULL, alarm has been added
+	3. If iAlarmActionStreamId is not KNullStreamId and iAlarmAction is not KNullDesC, The AlarmAction could be updated
+
+@internalComponent
+@return TAgnAlarmActionChange value indicating the type of change
+*/
+	{
+	TAgnDataChange change = EAgnDataNoChange;
+	
+	if ( IsFlagSet(EAgnAlarmActionDeleted) )
+		{
+		change = EAgnDataDeleted;
+		}
+	else if ( iAlarmAction )
+		{
+		if ( iAlarmActionStreamId == KNullStreamId )
+			{
+			change = EAgnDataAdded;
+			}
+		else
+			{
+			change = EAgnDataUpdated;
+			}
+		}
+
+	return change;
+	}
+
+
+EXPORT_C const TStreamId& CAgnEntry::DescriptionStreamId() const
+/** Gets the ID of the embedded stream store in which the description has been stored.
+
+@internalComponent
+@return The ID for the stream store in which the description has been stored.
+*/
+	{
+	return iDescriptionStreamId;
+	}
+
+
+EXPORT_C void CAgnEntry::SetDescriptionStreamId(const TStreamId& aStreamId)
+/** Sets the ID of the embedded stream store in which the description has been stored.
+
+@internalComponent
+@param The ID for the stream store in which the description has been stored.
+*/
+	{
+	iDescriptionStreamId = aStreamId;
+	}
+
+
+EXPORT_C void CAgnEntry::SetSummaryStreamId(const TStreamId& aStreamId)
+/** Sets the ID of the embedded stream store in which the summary has been stored.
+
+@internalComponent
+@param The ID for the stream store in which the summary has been stored.
+*/
+	{
+	iSummaryStreamId = aStreamId;
+	}
+
+EXPORT_C const TStreamId& CAgnEntry::SummaryStreamId() const
+/** Gets the ID of the embedded stream store in which the summary has been stored.
+
+@internalComponent
+@return The ID for the stream store in which the summary has been stored.
+*/
+	{
+	return iSummaryStreamId;
+	}
+
+/**
+@internalComponent
+@capability None
+@return   TPtrC8
+*/	
+EXPORT_C const TDesC8& CAgnEntry::Guid() const
+	{
+	return iGsData->Guid();
+	}
+
+EXPORT_C void CAgnEntry::SetMethod(CCalEntry::TMethod aMethod)
+	{
+	iGsData->SetMethod(aMethod);
+	}
+
+EXPORT_C void CAgnEntry::SetGuid(HBufC8* aGuid)
+/**
+@internalComponent
+*/
+	{
+	iGsData->SetGuid(aGuid);
+	}
+
+EXPORT_C CGsData::TGsDataType CAgnEntry::GsDataType() const
+/**
+@internalComponent
+*/
+	{
+	return iGsData->GsDataType();
+	}
+
+EXPORT_C CCalEntry::TMethod CAgnEntry::Method() const
+/**
+@internalComponent
+*/
+	{
+	return iGsData->Method();
+	}
+
+EXPORT_C TInt CAgnEntry::SequenceNumber() const
+/**
+@internalComponent
+*/
+	{
+	return iGsData->SequenceNumber();
+	}
+
+
+EXPORT_C void CAgnEntry::SetSequenceNumber(TInt aSeqNum)
+	{
+	iGsData->SetSequenceNumber(aSeqNum);
+	}	
+/**
+@internalComponent
+@capability None
+@return   TTime
+*/
+EXPORT_C TAgnCalendarTime CAgnEntry::RecurrenceId() const
+	{
+	return iGsData->RecurrenceId();
+	}
+
+/** 
+@internalComponent
+*/
+EXPORT_C CalCommon::TRecurrenceRange CAgnEntry::RecurrenceRange() const
+	{
+	return iGsData->RecurrenceRange();
+	}
+		
+EXPORT_C TCalLocalUid CAgnEntry::ParentId() const
+	{
+	__ASSERT_DEBUG(GsDataType() == CGsData::EChild, Panic(EAgmErrNotChildEntry));
+
+	return (static_cast<CGsChildData*>(iGsData)->ParentId());
+	}
+
+EXPORT_C void CAgnEntry::SetParentId(TCalLocalUid aParentId)
+	{
+	__ASSERT_DEBUG(GsDataType() == CGsData::EChild, Panic(EAgmErrNotChildEntry));
+
+	static_cast<CGsChildData*>(iGsData)->SetParentId(aParentId);
+	}
+
+EXPORT_C void CAgnEntry::UpdateRecurrenceIdL(const TAgnCalendarTime& aRecId)
+	{
+	__ASSERT_DEBUG(GsDataType() == CGsData::EChild, Panic(EAgmErrNotChildEntry));
+	
+	CGsChildData* childData = static_cast<CGsChildData*>(iGsData);
+	TTimeIntervalHours hoursChange;
+	aRecId.UtcL().HoursFrom(RecurrenceId().UtcL(), hoursChange);
+	childData->SetRecurrenceId(aRecId);
+	}
+
+EXPORT_C void CAgnEntry::SetRecurrenceRangeL(CalCommon::TRecurrenceRange aRange)
+	{
+	if (RptDef())
+		{
+		__ASSERT_DEBUG(aRange == CalCommon::EThisAndFuture || aRange == CalCommon::EThisAndPrior, User::Leave(KErrCorrupt));
+		}
+	else
+		{
+		__ASSERT_DEBUG(aRange == CalCommon::EThisOnly, User::Leave(KErrCorrupt));
+		}
+
+	CGsChildData* childData = static_cast<CGsChildData*>(iGsData);
+	childData->SetRecurrenceRange(aRange);
+	}
+
+EXPORT_C TBool CAgnEntry::HasChildren() const
+	{
+	if (GsDataType() == CGsData::EParent && ChildIds().Count() > 0)
+		{
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+EXPORT_C const RArray<TGsChildRefData>& CAgnEntry::ChildIds() const
+	{
+	__ASSERT_DEBUG(GsDataType() == CGsData::EParent, Panic(EAgmErrNotParentEntry));
+
+	return (static_cast<CGsParentData*>(iGsData)->ChildIds());
+	}
+	
+EXPORT_C void CAgnEntry::AddChildIdL(const TGsChildRefData& aChildRefData)
+	{
+	__ASSERT_DEBUG(GsDataType() == CGsData::EParent, Panic(EAgmErrNotParentEntry));
+
+	static_cast<CGsParentData*>(iGsData)->AddChildIdL(aChildRefData);
+	}
+	
+EXPORT_C void CAgnEntry::RemoveChildId(TCalLocalUid aId)
+	{
+	__ASSERT_DEBUG(GsDataType() == CGsData::EParent, Panic(EAgmErrNotParentEntry));
+
+	static_cast<CGsParentData*>(iGsData)->RemoveChildId(aId);
+	}
+
+EXPORT_C void CAgnEntry::SetRecurrenceIdFromParentL(const CAgnEntry& aParentEntry)
+	{//Set the recurrence id and range by its parent data.
+	__ASSERT_DEBUG(GsDataType() == CGsData::EChild, Panic(EAgmErrNotChildEntry));
+	TAgnCalendarTime recurid = RecurrenceId();
+	
+	CGsChildData* childGsData = static_cast<CGsChildData*>(iGsData);
+	if ( ! recurid.IsSet())
+		{
+		recurid = aParentEntry.GetChildRecurrenceId(LocalUid());
+		childGsData->SetRecurrenceId(recurid);
+		}
+	}
+
+ TAgnCalendarTime CAgnEntry::GetChildRecurrenceId(TCalLocalUid aChildId) const
+	{//Get the recurrence id for one of its children
+	const RArray<TGsChildRefData>& KChildIds = ChildIds();
+
+	const TInt KCount((KChildIds.Count()));
+	TAgnCalendarTime recurId;
+	
+	for (TInt i = 0; i < KCount; ++i)
+		{
+		if (KChildIds[i].ChildId() == aChildId)
+			{
+			recurId = KChildIds[i].RecurrenceId();
+			break;
+			}
+		}
+	return recurId;
+	}
+
+
+EXPORT_C void CAgnEntry::SetAlarmAction(CAgnContent* aAlarmAction)
+/** Set an alarm action object to the Agenda entry.
+The Agenda Entry takes ownership of the passed object.
+@internalComponent
+*/
+	{
+	if(iAlarmAction && !aAlarmAction && iAlarmActionStreamId != KNullStreamId)
+		{
+		SetFlagOn(EAgnAlarmActionDeleted);
+		}
+
+	delete iAlarmAction;
+
+	// Take ownership of the content.
+	iAlarmAction = aAlarmAction;
+	}
+
+
+EXPORT_C TBool CAgnEntry::AlarmActionIsLoaded() const
+/** Check if Alarm action object is loaded from the stream
+@internalComponent
+*/
+	{
+	if ( !iAlarmAction && iAlarmActionStreamId != KNullStreamId && ! IsFlagSet(EAgnAlarmActionDeleted) )
+		{
+		return EFalse;
+		}		
+
+	return ETrue;
+	}
+
+	
+EXPORT_C CAgnContent* CAgnEntry::AlarmAction() const
+/** Get the Alarm action object
+@internalComponent
+*/
+	{
+	return iAlarmAction;
+	}
+
+
+EXPORT_C void CAgnEntry::SetAlarmActionStreamId(const TStreamId& aStreamId)
+/** Set the Alarm action stream id
+@internalComponent
+*/
+	{
+	iAlarmActionStreamId = aStreamId;
+	}
+
+
+EXPORT_C const TStreamId& CAgnEntry::AlarmActionStreamId() const
+/** Get the Alarm action stream id
+@internalComponent
+*/
+	{
+	return iAlarmActionStreamId;
+	}
+
+EXPORT_C void CAgnEntry::AddAttachmentL(CAgnAttachment* aAttachment)
+	{
+	if (!iAttachments)
+		{
+		iAttachments = new (ELeave) RPointerArray<CAgnAttachment>;
+		}
+	if (aAttachment)
+		{
+		iAttachments->AppendL(aAttachment);	
+		}
+	}
+
+EXPORT_C TInt CAgnEntry::DeleteAttachmentL(const CAgnAttachment& aAttachment)
+	{
+	TInt ret = -1;
+	if (iAttachments)
+		{
+		const TInt KAttachmentCount = iAttachments->Count();
+		for (TInt i = 0; i < KAttachmentCount; ++i)
+			{
+			CAgnAttachment* attachToCompare = (*iAttachments)[i];
+			if (attachToCompare->CompareL(aAttachment))
+				{
+				ret = i;
+				delete attachToCompare;
+				iAttachments->Remove(i);
+				break;
+				}
+			}
+		}
+	return ret;
+	}
+
+EXPORT_C CAgnAttachment& CAgnEntry::Attachment(TInt aIndex) const
+	{
+	return *(*iAttachments)[aIndex];
+	}
+
+EXPORT_C TInt CAgnEntry::AttachmentCount() const
+	{
+	if (iAttachments)
+		{
+		return iAttachments->Count();
+		}
+	return 0;
+	}
+
+/** 
+Sets the user integer for this entry.
+
+@param aUserInt The new value of the user integer. 
+@internalComponent
+*/
+EXPORT_C void CAgnEntry::SetUserInt( TUint32 aUserInt )
+    {
+    CAgnSimpleEntry::SetUserInt(aUserInt);
+    }
+
+/**
+Gets the user integer of this entry.
+
+@return The user integer.
+@internalComponent
+*/
+EXPORT_C TUint32 CAgnEntry::UserInt() const
+    {
+    return CAgnSimpleEntry::UserInt();
+    }
+
+EXPORT_C void CAgnEntry::ExternalizeToBufferL(RWriteStream& aWriteStream) const
+/** Used for passing the data to the between client and server
+@internalComponent
+*/
+	{
+	ExternalizeEntryL(aWriteStream, ETrue);
+	ExternalizeGsDataL(aWriteStream, ETrue);
+		
+	if ( iDescription )
+		{
+		aWriteStream.WriteUint8L(ETrue);
+		aWriteStream << *iDescription;	
+		}
+	else
+		{
+		aWriteStream.WriteUint8L(EFalse);	
+		}
+
+	if ( iSummary )
+		{
+		aWriteStream.WriteUint8L(ETrue);
+		aWriteStream << *iSummary;	
+		}
+	else
+		{
+		aWriteStream.WriteUint8L(EFalse);	
+		}
+	
+	TBool hasAlarmContent = iAlarmAction?ETrue:EFalse;
+	aWriteStream.WriteUint8L(hasAlarmContent);
+	if ( hasAlarmContent )
+		{
+		aWriteStream << *iAlarmAction;
+		}
+
+	aWriteStream.WriteUint8L(IsFlagSet(EAgnAlarmActionDeleted));
+	}
+
+
+EXPORT_C void CAgnEntry::InternalizeFromBufferL(RReadStream& aReadStream)
+/** Used for passing the data to the between client and server
+@internalComponent
+*/
+	{
+	InternalizeEntryL(aReadStream, ETrue);
+	InternalizeGsDataL(aReadStream, ETrue);
+
+	delete iDescription;
+	iDescription = NULL;
+	if(aReadStream.ReadUint8L())//iDescription is not NULL
+		{//The following does not allocate KMaxTInt cells on heap
+		iDescription = HBufC::NewL(aReadStream, KMaxTInt); 	
+		}
+	
+	delete iSummary;
+	iSummary = NULL;
+	
+	if(aReadStream.ReadUint8L())//iSummary is not NULL
+		{//The following does not allocate KMaxTInt cells on heap
+		iSummary = HBufC::NewL(aReadStream, KMaxTInt); 	
+		}
+
+	delete iAlarmAction;
+	iAlarmAction = NULL;
+	TBool hasAlarmContent = aReadStream.ReadUint8L();
+	if ( hasAlarmContent )
+		{
+		iAlarmAction = new (ELeave) CAgnContent;
+		aReadStream >> *iAlarmAction; 
+		}
+
+	if (aReadStream.ReadUint8L())
+		{
+		SetFlagOn(EAgnAlarmActionDeleted);
+		}
+	else
+		{
+		SetFlagOff(EAgnAlarmActionDeleted);
+		}
+	// Externalize the entry details to the buffer
+	// Any rich text components will be stored in the textStream buffer
+	}
+
+
+EXPORT_C CCalEntry::TTransp CAgnEntry::BusyStatus() const
+/** Get transparency value
+@internalComponent
+*/
+	{
+	return static_cast<CCalEntry::TTransp>(iBusyStatus);
+	}
+
+
+EXPORT_C void CAgnEntry::SetBusyStatusL(CCalEntry::TTransp aBusyStatus)
+/** Set transparency value
+@internalComponent
+@leave KErrArgument if passed parameter is negative
+*/
+	{
+	if ( aBusyStatus < 0 )
+		{
+		User::Leave( KErrArgument );		
+		}
+		
+	iBusyStatus = aBusyStatus;
+	}
+
+EXPORT_C void CAgnEntry::GeoValue(TReal& aLatitude, TReal& aLongitude) const
+	{
+	aLatitude=iLatitude;
+	aLongitude=iLongitude;
+	}
+
+/** Set GEO - Latitude and Longitude values for the entry
+Latitude is bound between +-0-90 degrees
+Longitude is bound between +-0-180 degrees
+@internalComponent
+@leave KErrArgument if passed parameter is out of bounds.
+*/
+EXPORT_C void CAgnEntry::SetGeoValueL(const TReal& aLatitude, const TReal& aLongitude)
+	{
+	// Bounds checking
+	__ASSERT_ALWAYS(
+	((aLatitude >= KCalGEOMinLatitude && aLatitude <= KCalGEOMaxLatitude) || aLatitude == KGEODefaultValue) 
+	&& ((aLongitude >= KCalGEOMinLongitude && aLongitude <= KCalGEOMaxLongitude) || aLongitude == KGEODefaultValue), 
+	User::Leave(KErrArgument));
+	
+	// Truncate to KGEOMaxDecimals decimal places
+	TReal truncatedLatitude;
+	TReal truncatedLongitude;
+	Math::Round(truncatedLatitude,aLatitude,KCalGEOMaxDecimalPlaces);
+	Math::Round(truncatedLongitude,aLongitude,KCalGEOMaxDecimalPlaces);
+		
+	iLatitude = truncatedLatitude;
+	iLongitude = truncatedLongitude;
+	}
+
+// verify entry is valid before storing it
+EXPORT_C void CAgnEntry::VerifyBeforeStoreL()
+	{
+	//Check entry time
+	if ( Type() != CCalEntry::ETodo )
+		{
+		__ASSERT_ALWAYS(StartTime().IsSet(), Panic(EAgmErrTimeNotSet));
+		if ( Type() != CCalEntry::EReminder )
+			{
+			__ASSERT_ALWAYS(EndTime().IsSet(), Panic(EAgmErrTimeNotSet));
+			}
+		}
+	//Check repeating rule
+	if ( RptDef() )
+		{
+		// check entry's repeat rule valid
+		if ( RptDef()->InvariantL() != KErrNone )
+			{
+			const TAgnRpt* rptRule = RptDef()->RRule();
+			__ASSERT_ALWAYS(rptRule, User::Leave(KErrCorrupt)); // this can never be NULL if Invariant returns an error
+			
+			// if entry has only one instance, clear the repeat rule
+			if ( rptRule->InstanceCountL() == 1 )
+				{
+				RptDef()->ClearRRule();
+				}
+			else
+				{
+				User::Leave(KErrArgument);
+				}
+			}
+			
+		else if (RptDef()->Exceptions())
+			{
+			RptDef()->PruneExceptionsL();
+			}
+
+		//check the RDates here
+		TInt i = 0;
+		while (RptDef()->SporadicDateList() && i < RptDef()->SporadicDateList()->Count())
+			{
+			const TAgnCalendarTime& KSporadicDate = (*RptDef()->SporadicDateList())[i];
+			if (RptDef()->IsARepeatRuleDateInstanceL(KSporadicDate.LocalL()))
+				{
+				RptDef()->RemoveSporadicDate(KSporadicDate);
+				}
+			else if (EntryTime() == KSporadicDate)
+				{
+				// the DTSTART may not be checked in IsARepeatRuleDateInstance, so check it explicitly
+				RptDef()->RemoveSporadicDate(KSporadicDate);
+				}
+			else
+				{
+				// this sporadic date is ok
+				++i;
+				}
+			}
+
+		const TAgnRpt* rptRule = RptDef()->RRule();
+		if(!rptRule && !(RptDef()->HasSporadicDates()))
+			{
+			ClearRepeat();
+			}
+		}
+	}
+
+void CAgnEntry::SetFlagOn(TFlags aFlag)
+	{
+	iFlags |= aFlag;
+	}
+
+void CAgnEntry::SetFlagOff(TFlags aFlag)
+	{
+	iFlags &= ~aFlag;
+	}
+
+TBool CAgnEntry::IsFlagSet(TFlags aFlag) const
+	{
+	return (iFlags & aFlag);
+	}