commands/fcalendar/fcalendar.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/fcalendar/fcalendar.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,765 @@
+// fcalendar.cpp
+// 
+// Copyright (c) 2009 - 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "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:
+// Accenture - Initial contribution
+//
+
+#include "caliterator.h"
+#include <calsession.h>
+#include <calentryview.h>
+#include <calentry.h>
+#include <calalarm.h>
+#include <calrrule.h>
+#include <caluser.h>
+#include <calprogresscallback.h>
+#include <fshell/ioutils.h>
+
+using namespace IoUtils;
+
+
+// Destroy the RPointerArray
+void DestroyCalEntryRPointerArray(TAny* aPtr)
+    {
+    RPointerArray<CCalEntry>* self = static_cast<RPointerArray<CCalEntry>*> (aPtr);
+    self->ResetAndDestroy();
+    }
+
+
+
+enum TCurrentOperation
+	{
+	ECONewEntryView,
+	ECONone	
+	};
+
+class CCmdCalendar : public CCommandBase, public MCalProgressCallBack
+	{
+public:
+	static CCommandBase* NewLC();
+	~CCmdCalendar();
+private:
+	CCmdCalendar();
+
+	void DoListEntryL();
+	void DoDeleteEntryL();
+	void DoAddEntryL();
+	void DoChangeEntryL();
+	
+	void ReadCmdLineAmendEntryContentL(CCalEntry& aEntry);	
+	void ListGSDetailL(const TDesC8& aGlobalId, TInt aVerboseLevel);	
+	void PrintEntryDetailL(CCalEntry* aEntry, TInt aVerboseLevel);	
+	
+	void PrintAcceptedOptions();
+	
+	TInt CheckAlarmAlertServer();
+	
+	static const TDesC* UidName(TUid aUid);
+	static const TDesC* EntryMethodToString(CCalEntry::TMethod aEntryMethod);
+	static const TDesC* EntryStatusToString(CCalEntry::TStatus aEntryStatus);	
+	static const TDesC* EntryTypeToString(CCalEntry::TType aEntryType);	
+	static const TDesC* RepeatTypeToString(TCalRRule::TType aType);
+	void PrintTime(const TTime& aTime, TBool aNewline);	
+private: // From CCommandBase.
+	virtual const TDesC& Name() const;
+	virtual void DoRunL();
+	virtual void ArgumentsL(RCommandArgumentList& aArguments);
+	virtual void OptionsL(RCommandOptionList& aOptions);
+	
+private:	//MCalProgressCallBack
+	virtual void Progress(TInt aPercentageCompleted);
+	virtual void Completed(TInt aError);
+	virtual TBool NotifyProgress();
+	
+private:
+	CActiveSchedulerWait* iActiveWait;
+	TCurrentOperation iCurOpr;
+	
+	CCalSession* iCalSes;
+	CCalEntryView* iEntryView;
+	
+	RArray<TBool> iVerbose;
+	HBufC* iOptFileName;	//calendar database file full path
+	TInt iOptLocalId;		//local ID
+	HBufC* iOptGlobalID;
+	CCalEntry::TType iOptType;
+	HBufC* iOptSummary;
+	HBufC* iOptStartTime;
+	HBufC* iOptEndTime;
+
+	
+	enum 
+		{
+		EListEntry,
+		EDeleteEntry,
+		EAddEntry,
+		EChangeEntry,		
+		} iCommand;
+	};
+
+CCommandBase* CCmdCalendar::NewLC()
+	{
+	CCmdCalendar* self = new(ELeave) CCmdCalendar();
+	CleanupStack::PushL(self);
+	self->BaseConstructL();
+	return self;
+	}
+
+CCmdCalendar::CCmdCalendar()
+	{
+	iCurOpr = ECONone;
+	iActiveWait = new (ELeave) CActiveSchedulerWait;
+	}
+
+
+CCmdCalendar::~CCmdCalendar()
+	{
+	delete iOptFileName;
+	delete iOptGlobalID;
+	delete iOptSummary;	
+	delete iOptStartTime;
+	delete iOptEndTime;
+	delete iEntryView;
+	delete iCalSes;
+	delete iActiveWait;
+	iVerbose.Close();
+	}
+
+//////////////////////////////////////////////////////
+
+//virtual 
+void CCmdCalendar::Progress(TInt /*aPercentageCompleted*/)
+	{
+	;
+	}
+
+//virtual 
+void CCmdCalendar::Completed(TInt /*aError*/)
+	{
+	TBool bWaitStarted = iActiveWait->IsStarted();
+	ASSERT(bWaitStarted);
+	(void)bWaitStarted;
+	
+	if (iCurOpr == ECONewEntryView)
+		{
+		iActiveWait->AsyncStop();
+		}
+
+	iCurOpr = ECONone;
+	}
+
+TBool CCmdCalendar::NotifyProgress()
+	{
+	return ETrue;
+	}
+
+const TDesC& CCmdCalendar::Name() const
+	{
+	_LIT(KName, "fcalendar");
+	return KName;
+	}
+
+void CCmdCalendar::ArgumentsL(RCommandArgumentList& aArguments)
+	{
+	_LIT(KArgCommand, "command");
+	aArguments.AppendEnumL((TInt&)iCommand, KArgCommand);
+	}
+
+void CCmdCalendar::OptionsL(RCommandOptionList& aOptions)
+	{
+	_LIT(KOptVerbose, "verbose");
+	aOptions.AppendBoolL(iVerbose, KOptVerbose);
+
+	_LIT(KOptFile, "file");
+	aOptions.AppendStringL(iOptFileName, KOptFile);
+
+	_LIT(KOptLocalId, "local_id");
+	aOptions.AppendUintL((TUint&)iOptLocalId, KOptLocalId);
+
+	_LIT(KOptGlobalId, "global_id");
+	aOptions.AppendStringL(iOptGlobalID, KOptGlobalId);
+
+	_LIT(KOptType, "type");
+	aOptions.AppendEnumL((TInt&)iOptType, KOptType);
+
+	_LIT(KOptSummary, "summary");
+	aOptions.AppendStringL(iOptSummary, KOptSummary);
+
+	_LIT(KOptStartTime, "start_time");
+	aOptions.AppendStringL(iOptStartTime, KOptStartTime);
+
+	_LIT(KOptEndTime, "end_time");
+	aOptions.AppendStringL(iOptEndTime, KOptEndTime);
+	}
+
+//calendar have dependency on !AlamAlertServer,
+//this server is usually part of eikon and not likely to be started separately
+//we need to check if this server is up and running,
+//if not, no point to contiune
+//
+//return:
+//-1 (KErrNotFound): this server is not running
+//0 (KErrNone): OK
+TInt CCmdCalendar::CheckAlarmAlertServer()
+	{
+	TInt Ret;
+	TInt Res;
+	TFindServer findASServer(_L("!AlarmAlertServer"));
+	TFullName name;
+	Res = findASServer.Next(name);
+	
+	if (Res==KErrNotFound )
+		Ret = KErrNotFound;
+	else
+		Ret = KErrNone;
+	
+	return Ret;
+	}
+
+
+void CCmdCalendar::DoRunL()
+	{
+	TInt res;
+	res = CheckAlarmAlertServer();
+	LeaveIfErr(res, _L("!AlarmAlertServer not running"));
+	
+	TRAPD(err, iCalSes = CCalSession::NewL() );
+	LeaveIfErr(err, _L("Could not connect to Calendar server"));
+	
+	//open the calendar database file
+	if (iOptFileName && iOptFileName->Length()>0 ) 
+		{
+		Printf(_L("Calendar Database file: %S \r\n"), iOptFileName);
+		}
+	else
+		{
+		Printf(_L("Calendar Database file unspecified, by default S60 database file is c:Calendar\r\n"));
+		delete iOptFileName; iOptFileName = NULL;
+		iOptFileName = HBufC::NewL(128);
+		*iOptFileName = _L("c:Calendar");
+		}
+	
+	//open database file
+	TRAP(err, iCalSes->OpenL(*iOptFileName) );
+	LeaveIfErr(err, _L("Could not open database file"));
+	
+	//Create an entry view 
+	iCurOpr = ECONewEntryView;
+	TRAP(err, iEntryView = CCalEntryView::NewL(*iCalSes, *this));
+	LeaveIfErr(err, _L("Could not create entry view"));
+	
+	//entry view takes a long time to build index, and we must not do anything 
+	//until we received callback, therefore, must wait here.
+	iActiveWait->Start();
+	
+	///////////////////////////////////////////////////////////////////////////
+	
+	switch (iCommand)
+		{
+	case EListEntry:
+		DoListEntryL();
+		break;
+	case EDeleteEntry:
+		DoDeleteEntryL();	
+		break;
+	case EAddEntry:
+		DoAddEntryL();
+		break;
+	case EChangeEntry:
+		DoChangeEntryL();
+		break;
+		};
+
+	}
+
+void CCmdCalendar::DoChangeEntryL()
+	{
+	//compulsory: globalid, these can not be changed later
+	if (!iOptGlobalID || iOptGlobalID->Length()== 0)
+		LeaveIfErr(KErrArgument, _L("No global id specified. Use -g to specify one"));
+	
+	//type cannot be changed by calendar API, warning user of this fact
+	if (iOptions.IsPresent(&iOptType))
+		{
+		Printf(_L("Type is not allowed to change, this option (-t) will be ignored.\r\n"));
+		}
+		
+	RPointerArray<CCalEntry> CalEntryArray;
+	CleanupStack::PushL(TCleanupItem(DestroyCalEntryRPointerArray, &CalEntryArray));
+		
+	TBuf8<128> TmpGlobalId;
+	TmpGlobalId.Copy(*iOptGlobalID);
+	HBufC8* pGlobalId = HBufC8::New(128);
+	CleanupStack::PushL(pGlobalId);
+	*pGlobalId = TmpGlobalId;
+	
+	//do an extra check if the same global ID is already used.
+	iEntryView->FetchL(*pGlobalId, CalEntryArray);
+	CleanupStack::PopAndDestroy(pGlobalId);
+	pGlobalId = NULL;	//this HBufC is owned by CalEntry
+	
+	TInt Cnt = CalEntryArray.Count();
+	if (Cnt == 0)
+		LeaveIfErr(KErrNotFound, _L("No such Global ID."));					
+
+	Printf(_L("%d entries found\r\n"), Cnt);
+			
+	CCalEntry* pEntry = CalEntryArray[0];
+	
+	//amend necessary calendar entry properties
+	ReadCmdLineAmendEntryContentL(*pEntry);
+		
+	TInt SucessfulEntryCnt = 0;
+	iEntryView->UpdateL(CalEntryArray, SucessfulEntryCnt);
+	
+	Printf(_L("%d entries changed\r\n"), SucessfulEntryCnt);
+	
+	CleanupStack::PopAndDestroy();	
+	}
+
+void CCmdCalendar::DoAddEntryL()
+	{
+	//compulsory: globalid, type, these can not be changed later
+	if (!iOptGlobalID || iOptGlobalID->Length()== 0)
+		LeaveIfErr(KErrArgument, _L("No global id specified. Use -g to specify one"));							
+	if (!iOptions.IsPresent(&iOptType))
+		LeaveIfErr(KErrArgument, _L("No type specified. Use -t to specify one"));
+		
+	RPointerArray<CCalEntry> CalEntryArray;
+	CleanupStack::PushL(TCleanupItem(DestroyCalEntryRPointerArray, &CalEntryArray));
+		
+	TBuf8<128> TmpGlobalId;
+	TmpGlobalId.Copy(*iOptGlobalID);
+	HBufC8* pGlobalId = HBufC8::New(128);
+	CleanupStack::PushL(pGlobalId);
+	*pGlobalId = TmpGlobalId;
+	
+	//do an extra check if the same global ID is already used.
+	//if yes, then adding with such global id is not allowed
+		{
+		iEntryView->FetchL(*pGlobalId, CalEntryArray);
+		TInt Cnt = CalEntryArray.Count();
+		if (Cnt > 0)
+			LeaveIfErr(KErrAlreadyExists, _L("The same Global ID is already used."));					
+		}
+	
+	CCalEntry* pEntry = CCalEntry::NewL(iOptType, pGlobalId, 
+			CCalEntry::EMethodNone, 0);
+	CleanupStack::Pop(pGlobalId);
+	pGlobalId = NULL;	//this HBufC is owned by CalEntry
+		
+	CalEntryArray.Append(pEntry);
+	
+	//amend necessary calendar entry properties
+	ReadCmdLineAmendEntryContentL(*pEntry);
+		
+	TInt SucessfulEntryCnt = 0;
+	iEntryView->StoreL(CalEntryArray, SucessfulEntryCnt);
+	
+	Printf(_L("%d entries added\r\n"), SucessfulEntryCnt);
+	
+	CleanupStack::PopAndDestroy();	
+	}
+
+void CCmdCalendar::DoDeleteEntryL()
+	{
+	//TInt VerboseLevel = iVerbose.Count();
+	if (iOptGlobalID && iOptGlobalID->Length())
+		{
+		RPointerArray<CCalEntry> CalEntryArray;
+		CleanupStack::PushL(TCleanupItem(DestroyCalEntryRPointerArray, &CalEntryArray));
+
+		//FetchL is not Async
+		//and there will be new CCalEntry objects generared 
+		//and pointer stored in CalEntryArray
+		TBuf8<256> GlobalID;
+		GlobalID.Copy(*iOptGlobalID);
+		
+		iEntryView->FetchL(GlobalID, CalEntryArray);
+		
+		TInt EntryCount = CalEntryArray.Count();
+		Printf(_L("%d Entries found\r\n"), EntryCount);
+		
+		for (TInt i=0; i<EntryCount; i++)
+			{
+			CCalEntry* pEntry = CalEntryArray[0];
+			CalEntryArray.Remove(0);				
+			
+			CleanupStack::PushL(pEntry);
+			iEntryView->DeleteL(*pEntry);
+			CleanupStack::PopAndDestroy(pEntry);
+			}		
+		
+		Printf(_L("%d Entries deleted\r\n"), EntryCount);
+		CleanupStack::PopAndDestroy();
+		}
+	else
+		{
+		LeaveIfErr(KErrArgument, _L("No global id specified. Use -g to specify one"));							
+		}	
+	}
+
+//list all agenda entry in the agenda server
+void CCmdCalendar::DoListEntryL()
+	{
+	TInt VerboseLevel = iVerbose.Count();
+	
+	CCalIter* pIter = CCalIter::NewL(*iCalSes);
+	CleanupStack::PushL(pIter);
+	
+	const TDesC8* pGlb = &(pIter->FirstL());
+	TBuf<128> GlbId;
+	
+	while(*pGlb != KNullDesC8)
+		{	
+		GlbId.Copy(*pGlb);
+		Printf(_L("================================\r\n"));
+		Printf(_L("Group Scheduling Entry, Global ID: %S\r\n"), &GlbId);
+		ListGSDetailL(*pGlb, VerboseLevel);
+		
+		pGlb = &(pIter->NextL());
+		}		
+	
+	CleanupStack::PopAndDestroy(pIter);
+	}
+
+//this function read user command line options,
+//and amend the corresponding Entry properties
+//
+void CCmdCalendar::ReadCmdLineAmendEntryContentL(CCalEntry& aEntry)
+	{
+	TInt res;
+	//summary is optional
+	if (iOptSummary && iOptSummary->Length() > 0)
+		aEntry.SetSummaryL(*iOptSummary);	
+
+	TCalTime StartTime = aEntry.StartTimeL();
+	TCalTime EndTime = aEntry.EndTimeL();
+
+	if (iOptStartTime && iOptStartTime->Length() > 0)
+		{
+		TTime Tmp(Time::NullTTime());
+		res = Tmp.Parse(*iOptStartTime);
+		if (res >= 0)
+			{
+			Printf(_L("StartTime recognised as ") );
+			PrintTime(Tmp, ETrue);
+			StartTime.SetTimeUtcL(Tmp);					
+			}
+		else
+			{
+			Printf(_L("Start Date/Time format not recogised.\r\n") );			
+			}		
+		}
+	if (iOptEndTime && iOptEndTime->Length() > 0)
+		{
+		TTime Tmp(Time::NullTTime());
+		res = Tmp.Parse(*iOptEndTime);		
+		if (res >= 0)
+			{
+			Printf(_L("EndTime recognised as ") );
+			PrintTime(Tmp, ETrue);
+			EndTime.SetTimeUtcL(Tmp);		
+			}
+		else
+			{
+			Printf(_L("End Date/Time format not recogised.\r\n") );			
+			}		
+		
+		}
+	
+	aEntry.SetStartAndEndTimeL(StartTime, EndTime);
+	
+	if (iOptLocalId)
+		{
+		TCalLocalUid LocalId = (TCalLocalUid) iOptLocalId;
+		aEntry.SetLocalUidL(LocalId);		
+		}	
+	}
+
+
+//verbose level
+//-v = 1, -vv = 2
+//
+void CCmdCalendar::ListGSDetailL(const TDesC8& aGlobalId, TInt aVerboseLevel)
+	{
+	RPointerArray<CCalEntry> CalEntryArray;
+	CleanupStack::PushL(TCleanupItem(DestroyCalEntryRPointerArray, &CalEntryArray));
+
+	//FetchL is not Async
+	//and there will be new CCalEntry objects generared 
+	//and pointer stored in CalEntryArray  
+	iEntryView->FetchL(aGlobalId, CalEntryArray);
+	
+	TInt Count = CalEntryArray.Count();
+	for (TInt i=0; i<Count; i++)
+		{
+		CCalEntry* pCalEntry= CalEntryArray[0];
+		CalEntryArray.Remove(0);		
+		CleanupStack::PushL(pCalEntry);
+		
+		//make sure leave does not occur inside this scope, 
+		//or contents in CalEntryArray may not be cleaned
+		TRAP_IGNORE(PrintEntryDetailL(pCalEntry, aVerboseLevel));
+		
+		CleanupStack::PopAndDestroy(pCalEntry);
+		}
+	
+	
+	CleanupStack::PopAndDestroy();
+	}
+
+
+void CCmdCalendar::PrintEntryDetailL(CCalEntry* aEntry, TInt aVerboseLevel)
+	{
+	//this matches the Group Scheduling global ID, no need to print it out
+	//const TDesC8& EntryID = aEntry->UidL();	
+	
+	//for verbose level 0
+	//entry type, summery, start time, end time, priority
+	CCalEntry::TType EntryType = aEntry->EntryTypeL();
+	const TDesC& EntrySummary = aEntry->SummaryL();
+	TCalTime EntryStartTime = aEntry->StartTimeL();
+	TCalTime EntryEndTime = aEntry->EndTimeL();
+	
+	TCalTime EntryCompTime = aEntry->CompletedTimeL();
+	TCalTime EntryModDate = aEntry->LastModifiedDateL();
+	
+	TUint EntryPriority = aEntry->PriorityL();
+
+	Printf(_L("Type:%S Priority: %u Summary:%S\r\n"), 
+			EntryTypeToString(EntryType), EntryPriority, &EntrySummary);
+		
+	Printf(_L(" StartTime:"));
+	PrintTime(EntryStartTime.TimeUtcL(), EFalse);
+	
+	Printf(_L(" EndTime:"));
+	PrintTime(EntryEndTime.TimeUtcL(), EFalse);
+
+	Printf(_L("\r\n"));
+	Printf(_L(" CompletedTime:"));
+	PrintTime(EntryCompTime.TimeUtcL(), EFalse);
+	
+	Printf(_L(" Last Modified:"));
+	PrintTime(EntryModDate.TimeUtcL(), EFalse);
+
+	Printf(_L("\r\n"));
+	
+	
+	if (aVerboseLevel < 1)
+		return;
+	
+	//local id, location, status, method, description
+	TCalLocalUid EntryLocalId = aEntry->LocalUidL();	
+	const TDesC& EntryLocation = aEntry->LocationL();
+	CCalEntry::TStatus EntryStatus = aEntry->StatusL();
+	CCalEntry::TMethod EntryMethod = aEntry->MethodL();
+	const TDesC& EntryDesc = aEntry->DescriptionL();
+	TInt EntrySequenceNo = aEntry->SequenceNumberL();
+	
+	Printf(_L(" LocalId:%u, SeqNo:%d,Location:%S Description:%S\r\n"),
+			EntryLocalId, EntrySequenceNo, &EntryLocation, &EntryDesc);
+	Printf(_L(" Status:%S Method:%S\r\n"),
+			EntryStatusToString(EntryStatus), EntryMethodToString(EntryMethod));
+	
+	
+	//alarm
+	CCalAlarm* pAlarm = aEntry->AlarmL();
+	TPtrC AlarmYesNo = (pAlarm)?_L("Yes"):_L("No");
+	Printf(_L(" Alarm: %S "), &AlarmYesNo);
+	
+	if (pAlarm && aVerboseLevel > 1)
+		{
+		CleanupStack::PushL(pAlarm);
+		const TDesC& AlarmSound = pAlarm->AlarmSoundNameL();
+		TTimeIntervalMinutes AlarmOffset = pAlarm->TimeOffset();
+		
+		Printf(_L("AlarmSound:%S, MinutesInAdvance:%d"), 
+				&AlarmSound, AlarmOffset.Int());
+		
+		//CCalContent is optional, will be included from calalarm if it's present
+#ifdef __CALCONTENT_H__
+		CCalContent* pAlarmContent = pAlarm->AlarmAction();
+		if (pAlarmContent)
+			{
+			const TDesC8& AlarmContent = pAlarmContent->Content();
+			const TDesC8& AlarmMime = pAlarmContent->MimeType();
+
+			Printf(_L8("\r\nAlarmContent:%S, AlarmMime:%S "), 
+					&AlarmContent, &AlarmMime);
+			
+			}
+#endif
+		CleanupStack::PopAndDestroy(pAlarm);
+		}
+	Printf(_L("\r\n"));
+	
+	//repeat rules
+	TCalRRule RepeatRule;
+	TBool bRepeat = aEntry->GetRRuleL(RepeatRule);
+	TPtrC RepeatYesNo = (bRepeat)?_L("Yes"):_L("No");
+	Printf(_L(" Repeat: %S "), &RepeatYesNo);
+	
+	if (bRepeat && aVerboseLevel > 1)
+		{
+		TCalRRule::TType RepeatType = RepeatRule.Type();
+		TInt RepeatInterval = RepeatRule.Interval();
+		TUint RepeatCount = RepeatRule.Count();
+
+		Printf(_L("RepeatType: %S Interval: %d Count:%u\r\n"),
+				RepeatTypeToString(RepeatType), RepeatInterval, RepeatCount);
+		TCalTime RepeatStart = RepeatRule.DtStart();
+		TCalTime RepeatUntil = RepeatRule.Until();
+		
+		Printf(_L(" RepeatStart:"));
+		PrintTime(RepeatStart.TimeUtcL(), EFalse);
+		
+		Printf(_L(" RepeatUntil:"));
+		PrintTime(RepeatUntil.TimeUtcL(), EFalse);
+		}
+	Printf(_L("\r\n"));
+		
+	//attendee, in most of phone implementation it is not used
+	RPointerArray<CCalAttendee>& AttendeeArray = aEntry->AttendeesL();
+	TInt AttendeeCnt = AttendeeArray.Count();
+	TPtrC AttendeeYesNo = (AttendeeCnt>0)?_L("Yes"):_L("No");
+	Printf(_L(" Attendee: %S "), &AttendeeYesNo);
+
+	if (AttendeeCnt>0 && aVerboseLevel > 1)
+		{
+		for (TInt i=0; i<AttendeeCnt; i++)
+			{
+			CCalAttendee* pAttendee = AttendeeArray[i];
+			const TDesC& AttendeeName = pAttendee->CommonName();
+			Printf(_L("Attendee:%S "), &AttendeeName);
+			}
+		}
+	Printf(_L("\r\n"));
+		
+	}
+
+//print the accepted options from the command line
+void CCmdCalendar::PrintAcceptedOptions()
+	{
+	}
+
+
+void CCmdCalendar::PrintTime(const TTime& aTime, TBool aNewline)
+	{
+	
+	TTime NullTime = Time::NullTTime();
+	if (aTime == NullTime) 
+		{
+		Printf(_L("(NullTime)"));
+		}
+	else
+		{
+		_LIT8(KDateTimeFormat, "%d-%02d-%02d %02d:%02d:%02d");
+		TDateTime dt = aTime.DateTime();
+		Printf(KDateTimeFormat, dt.Year(), dt.Month()+1, dt.Day()+1, dt.Hour(), dt.Minute(), dt.Second());
+		}
+	
+	if (aNewline) Printf(_L("\r\n"));
+	}
+
+
+#define CASE_LIT(x) case x: { _LIT(KName, #x); return &KName; }
+
+
+const TDesC* CCmdCalendar::RepeatTypeToString(TCalRRule::TType aType)
+	{
+	switch(aType)
+		{
+		CASE_LIT(TCalRRule::EInvalid)
+		CASE_LIT(TCalRRule::EDaily)
+		CASE_LIT(TCalRRule::EWeekly)
+		CASE_LIT(TCalRRule::EMonthly)
+		CASE_LIT(TCalRRule::EYearly)
+		default:
+			{
+			_LIT(KUnknown, "Unknown");
+			return &KUnknown;
+			}
+		}
+	}
+
+const TDesC* CCmdCalendar::EntryMethodToString(CCalEntry::TMethod aEntryMethod)
+	{
+	switch(aEntryMethod)
+		{
+		CASE_LIT(CCalEntry::EMethodNone)
+		CASE_LIT(CCalEntry::EMethodPublish)
+		CASE_LIT(CCalEntry::EMethodRequest)
+		CASE_LIT(CCalEntry::EMethodReply)
+		CASE_LIT(CCalEntry::EMethodAdd)
+		CASE_LIT(CCalEntry::EMethodCancel)
+		CASE_LIT(CCalEntry::EMethodRefresh)
+		CASE_LIT(CCalEntry::EMethodCounter)
+		CASE_LIT(CCalEntry::EMethodDeclineCounter)
+		default:
+			{
+			_LIT(KUnknown, "Unknown");
+			return &KUnknown;
+			}
+		}
+	}
+
+const TDesC* CCmdCalendar::EntryStatusToString(CCalEntry::TStatus aEntryStatus)
+	{
+	switch(aEntryStatus)
+		{
+		CASE_LIT(CCalEntry::ETentative)
+		CASE_LIT(CCalEntry::EConfirmed)
+		CASE_LIT(CCalEntry::ECancelled)
+		CASE_LIT(CCalEntry::ETodoNeedsAction)
+		CASE_LIT(CCalEntry::ETodoCompleted)
+		CASE_LIT(CCalEntry::ETodoInProcess)
+		CASE_LIT(CCalEntry::ENullStatus)
+		default:
+			{
+			_LIT(KUnknown, "Unknown");
+			return &KUnknown;
+			}
+		}
+	}
+
+const TDesC* CCmdCalendar::EntryTypeToString(CCalEntry::TType aEntryType)
+	{
+	switch(aEntryType)
+		{
+		CASE_LIT(CCalEntry::EAppt)
+		CASE_LIT(CCalEntry::ETodo)
+		CASE_LIT(CCalEntry::EEvent)
+		CASE_LIT(CCalEntry::EReminder)
+		CASE_LIT(CCalEntry::EAnniv)
+		default:
+			{
+			_LIT(KUnknown, "Unknown");
+			return &KUnknown;
+			}
+		}
+	}
+
+const TDesC* CCmdCalendar::UidName(TUid aUid)
+	{
+	switch (aUid.iUid)
+		{
+
+		default:
+			{
+			_LIT(KUnknown, "Unknown");
+			return &KUnknown;
+			}
+		}
+	}
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+
+EXE_BOILER_PLATE(CCmdCalendar)
+