calendarengines/agnversit2/src/AgnVersit2Importer.cpp
changeset 0 f979ecb2b13e
child 29 12af337248b1
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     1 /*
       
     2 * Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   This file contains iCal importer implementation.
       
    15 *                Converts iCal data to symbian agenda entry.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 // Class include.
       
    22 #include "AgnVersit2Importer.h"
       
    23 
       
    24 //debug
       
    25 #include "calendarengines_debug.h"
       
    26 
       
    27 // Agenda includes.
       
    28 #include <calalarm.h>			// For CCalAlarm
       
    29 #include <calcategory.h>		// For CCalCategory
       
    30 #include <calentry.h>			// For CCalEntry
       
    31 #include <calrrule.h>			// For CCalRRule
       
    32 #include <caltime.h>			// For CCalTime
       
    33 #include <caluser.h>			// For CCalUser
       
    34 #include <tzdefines.h>			// For TTzRuleDay
       
    35 #include <vtzrules.h>			// For CTzRules and TTzRule
       
    36 #include <CalenInterimUtils2.h>
       
    37 
       
    38 // Versit includes.
       
    39 #include "ICal.h"				// For CICal
       
    40 #include "ICalComponent.h"		// For CICalComponent
       
    41 #include "ICalKeyWords.h"		// For CICalKeyWords
       
    42 #include "ICalParser.h"			// For CICalParser
       
    43 #include "ICalProperty.h"		// For CICalProperty
       
    44 #include "ICalPropertyParam.h"	// For CICalPropertyParam
       
    45 #include "ICalRuleSegment.h"	// For CICalRuleSegment
       
    46 #include "ICalValue.h"			// For CICalValue
       
    47 
       
    48 // AgnVersit2 includes.
       
    49 #include "agnimportobserver.h"			// For MAgnImportObserver
       
    50 #include "AgnVersit2StringProvider.h"	// For CAgnVersit2StringProvider
       
    51 #include "CleanupPointerArray.h"		// For TCleanupPointerArray
       
    52 
       
    53 #include "AgnRRuleImporter.h"           // For CAgnRRuleImporter
       
    54 // Constants.
       
    55 
       
    56 
       
    57 /** A semi-colon character. */
       
    58 const TUint KAgnVersitTokenSemiColonVal =';';
       
    59 
       
    60 //
       
    61 //    CTzNamedRules
       
    62 //    =============
       
    63 //
       
    64 
       
    65 /**
       
    66 Constructor.
       
    67 @internalTechnology
       
    68 */
       
    69 CAgnVersit2Importer::CTzNamedRules::CTzNamedRules()
       
    70 	{
       
    71 	TRACE_ENTRY_POINT;
       
    72 	TRACE_EXIT_POINT;
       
    73 	}
       
    74 
       
    75 /**
       
    76 Destructor.
       
    77 @internalTechnology
       
    78 */
       
    79 CAgnVersit2Importer::CTzNamedRules::~CTzNamedRules()
       
    80 	{
       
    81 	TRACE_ENTRY_POINT;
       
    82 	
       
    83 	delete iRules;
       
    84 	delete iName;
       
    85 	
       
    86 	TRACE_EXIT_POINT;
       
    87 	}
       
    88 
       
    89 //
       
    90 //     CAgnVersit2Importer
       
    91 //     ===================
       
    92 //
       
    93 
       
    94 /**
       
    95 Constructs a new CAgnVersit2Importer and returns it.
       
    96 @param aStringProvider A string provider for obtaining resource strings from.
       
    97 @return a new CAgnVersit2Importer.
       
    98 @internalTechnology
       
    99 */
       
   100 CAgnVersit2Importer* CAgnVersit2Importer::NewL(CAgnVersit2StringProvider& aStringProvider)
       
   101 	{
       
   102 	TRACE_ENTRY_POINT;
       
   103 	
       
   104 	CAgnVersit2Importer* self = CAgnVersit2Importer::NewLC(aStringProvider);
       
   105 	CleanupStack::Pop(self);
       
   106 	
       
   107 	TRACE_EXIT_POINT;
       
   108 	return self;
       
   109 	}
       
   110 
       
   111 /**
       
   112 Constructs a new CAgnVersit2Importer and returns it. The object is left on the
       
   113 cleanup stack.
       
   114 @param aStringProvider A string provider for obtaining resource strings from.
       
   115 @return a new CAgnVersit2Importer.
       
   116 @internalTechnology
       
   117 */
       
   118 CAgnVersit2Importer* CAgnVersit2Importer::NewLC(CAgnVersit2StringProvider& aStringProvider)
       
   119 	{
       
   120 	TRACE_ENTRY_POINT;
       
   121 	
       
   122 	CAgnVersit2Importer* self = new (ELeave) CAgnVersit2Importer(aStringProvider);
       
   123 	CleanupStack::PushL(self);
       
   124 	self->ConstructL();
       
   125 	
       
   126 	TRACE_EXIT_POINT;
       
   127 	return self;
       
   128 	}
       
   129 
       
   130 /**
       
   131 Destructor.
       
   132 @internalTechnology
       
   133 */
       
   134 CAgnVersit2Importer::~CAgnVersit2Importer()
       
   135 	{
       
   136 	TRACE_ENTRY_POINT;
       
   137 	
       
   138 	iTzRules.ResetAndDestroy();
       
   139 	
       
   140 	TRACE_EXIT_POINT;
       
   141 	}
       
   142 
       
   143 /**
       
   144 Uses Versit2 to parse an input stream, and then converts the result into
       
   145 CCalEntry objects.
       
   146 @param aEntries The array to append entries to.
       
   147 @param aReadStream The stream to read iCalendar data from.
       
   148 @param aObserver Application interface for error reporting.
       
   149 @internalTechnology
       
   150 */
       
   151 void CAgnVersit2Importer::ImportL( RPointerArray<CCalEntry>& aEntries,
       
   152                                    RReadStream& aReadStream,
       
   153                                    MAgnImportObserver& aObserver )
       
   154 	{
       
   155 	TRACE_ENTRY_POINT;
       
   156 	
       
   157 	iImportObserver = &aObserver;
       
   158 
       
   159 	CICalParser* parser = CICalParser::NewLC();
       
   160 	parser->InternalizeL(aReadStream);
       
   161 
       
   162 	const TInt count = parser->CalCount();
       
   163 
       
   164 	for (TInt cal = 0; cal < count; ++cal)
       
   165 		{
       
   166 		CICal& calendar = parser->Cal(cal);
       
   167 		TRAPD(err, ImportICalL(aEntries, calendar));
       
   168 		iTzRules.ResetAndDestroy();
       
   169 		User::LeaveIfError(err);
       
   170 		}
       
   171 
       
   172 	CleanupStack::PopAndDestroy(parser);
       
   173 	TRACE_EXIT_POINT;
       
   174 	}
       
   175 
       
   176 /**
       
   177 Constructor.
       
   178 @internalTechnology
       
   179 */
       
   180 CAgnVersit2Importer::CAgnVersit2Importer(CAgnVersit2StringProvider& aStringProvider)
       
   181 	: iStringProvider(aStringProvider)
       
   182 	{
       
   183 	TRACE_ENTRY_POINT;
       
   184 	TRACE_EXIT_POINT;
       
   185 	}
       
   186 
       
   187 /**
       
   188 Internal construction.
       
   189 @internalTechnology
       
   190 */
       
   191 void CAgnVersit2Importer::ConstructL()
       
   192 	{
       
   193 	TRACE_ENTRY_POINT;
       
   194 	TRACE_EXIT_POINT;
       
   195 	}
       
   196 
       
   197 /**
       
   198 Takes a calendar object from Versit2 and converts it into a set of CCalEntry
       
   199 objects.
       
   200 @param aEntries The array to append entries to.
       
   201 @param aCal An object of type CICal from which to obtain data.
       
   202 @leave KErrAbort, or any other system wide error code.
       
   203 @internalTechnology
       
   204 */
       
   205 void CAgnVersit2Importer::ImportICalL(RPointerArray<CCalEntry>& aEntries, CICal& aCal)
       
   206 	{
       
   207 	TRACE_ENTRY_POINT;
       
   208 	
       
   209 	const RPointerArray<CICalComponent>& components = aCal.Components();
       
   210 
       
   211 	// Run through the timezones so that we know what other components are referring to:
       
   212 	iTzRules.ResetAndDestroy();
       
   213 	TInt com; // current component number
       
   214 	TInt comCount = components.Count();
       
   215 	for (com = 0; com < comCount && iResponse == MAgnImportObserver::EImpResponseContinue; ++com)
       
   216 		{
       
   217 		CICalComponent* component = components[com];
       
   218 
       
   219 		// We are only interested in timezones:
       
   220 		if (component->Type() == CICalBase::EICalTimeZone)
       
   221 			{
       
   222 			TRAPD(err, ImportTimezoneL(*component));
       
   223 			if (err)
       
   224 				{
       
   225 				// If there isn't a response, then it isn't a recoverable leave:
       
   226 				if (iResponse == MAgnImportObserver::EImpResponseContinue)
       
   227 					{
       
   228 					User::Leave(err);
       
   229 					}
       
   230 				// If there is a response, then we threw this after reporting an
       
   231 				// error to the observer, and we may be able to continue:
       
   232 				else if(iResponse == MAgnImportObserver::EImpResponseSkip)
       
   233 					{
       
   234 					iResponse = MAgnImportObserver::EImpResponseContinue;
       
   235 					}
       
   236 				}
       
   237 			}
       
   238 		}
       
   239 
       
   240 	// Run through the other components:
       
   241 	for (com = 0; com < comCount && iResponse == MAgnImportObserver::EImpResponseContinue; ++com)
       
   242 		{
       
   243 		CICalComponent* component = components[com];
       
   244 
       
   245 		// We aren't interested in timezones:
       
   246 		if (component->Type() != CICalBase::EICalTimeZone)
       
   247 			{
       
   248 			TRAPD(err, ImportComponentL(aCal, *component, aEntries));
       
   249 			if (err)
       
   250 				{
       
   251 				// If there isn't a response, then it isn't a recoverable leave:
       
   252 				if (iResponse == MAgnImportObserver::EImpResponseContinue)
       
   253 					{
       
   254 					User::Leave(err);
       
   255 					}
       
   256 				// If there is a response, then we threw this after reporting an
       
   257 				// error to the observer, and we may be able to continue:
       
   258 				else if(iResponse == MAgnImportObserver::EImpResponseSkip)
       
   259 					{
       
   260 					iResponse = MAgnImportObserver::EImpResponseContinue;
       
   261 					}
       
   262 				}
       
   263 			}
       
   264 		}
       
   265 
       
   266 	// If we have been asked to leave after an error, do so:
       
   267 	if (iResponse == MAgnImportObserver::EImpResponseLeave)
       
   268 		{
       
   269 		User::Leave(KErrAbort);
       
   270 		}
       
   271 	
       
   272 	TRACE_EXIT_POINT;
       
   273 	}
       
   274 
       
   275 /**
       
   276 *     IMPORT COMPONENT FUNCTIONS
       
   277 *     ==========================
       
   278 */
       
   279 
       
   280 /**
       
   281 Handles the importing of a single component, other than a timezone.
       
   282 @param aCal The calendar object from which we are importing
       
   283 @param aComponent The specific component we are importing
       
   284 @param aEntries The agenda entries onto which this component is to be appended.
       
   285 @internalTechnology
       
   286 */
       
   287 void CAgnVersit2Importer::ImportComponentL( const CICal& aCal,
       
   288                                             const CICalComponent& aComponent,
       
   289                                             RPointerArray<CCalEntry>& aEntries )
       
   290 	{
       
   291 	TRACE_ENTRY_POINT;
       
   292 	
       
   293 	// Get the UID:
       
   294 	HBufC8* entryUid = NULL;
       
   295 	const CICalProperty* propUid = aComponent.FindProperty(KICalUid());
       
   296 
       
   297 	if (!propUid)//(propUid && propUid->Values().Count() < 1)
       
   298 		{
       
   299 		// if UID is not present,generate using caleninterimutils api
       
   300 		CCalenInterimUtils2* interimUtils = CCalenInterimUtils2::NewL();
       
   301 		CleanupStack::PushL(interimUtils);
       
   302 		// get the global uid
       
   303 		entryUid = interimUtils->GlobalUidL();
       
   304 		CleanupStack::PopAndDestroy(interimUtils);
       
   305 		CleanupStack::PushL(entryUid);
       
   306 		}
       
   307 	else
       
   308 		{
       
   309 		entryUid = propUid->Values()[0]->BinaryLC();
       
   310 		}
       
   311 	
       
   312 	if(entryUid)
       
   313 	    {
       
   314 		// Import entry-type specific data:
       
   315 		switch (aComponent.Type())
       
   316 			{
       
   317 			case CICalBase::EICalEvent :
       
   318 				{
       
   319 				CCalEntry::TType eventType = CCalEntry::EEvent;
       
   320 				
       
   321 				//Check if we have a DTEND or DURATION
       
   322 				if (aComponent.FindProperty(KICalDtend()) || aComponent.FindProperty(KICalDuration()))
       
   323 					{
       
   324 					eventType = CCalEntry::EAppt;
       
   325 					}
       
   326 					
       
   327 				else
       
   328 					{
       
   329 					//Check if we have a DTSTART
       
   330 					if (aComponent.FindProperty(KICalDtstart()))
       
   331 						{
       
   332 						eventType = CCalEntry::EReminder;
       
   333 						}
       
   334 					
       
   335 					//Check if this is a yearly repeat
       
   336 					if (aComponent.FindProperty(KICalRRule()))
       
   337 						{
       
   338 						const CICalProperty* rrule = aComponent.FindProperty(KICalRRule());
       
   339 						const RPointerArray<CICalValue>& rulevalues = rrule->Values();
       
   340 	
       
   341 						if (rulevalues.Count() >= 1)
       
   342 							{
       
   343 							CICalRuleSegment::TFreq freq = CICalRuleSegment::EFreqDaily;
       
   344 							RPointerArray<CICalRuleSegment> recRules;
       
   345 							CleanupPointerArrayPushL(recRules);
       
   346 
       
   347 							// At this point we take ownership of the things which rules contains:
       
   348 							rulevalues[0]->GetRecurrenceRuleL(recRules);
       
   349 
       
   350 							// An RRule must have a frequency.
       
   351 							TInt pos = FindRuleSegment(recRules, CICalRuleSegment::ESegFreq);
       
   352 							if (pos != KErrNotFound)
       
   353 								{
       
   354 								ASSERT(recRules.Count() >= pos + 1);
       
   355 								freq = recRules[pos]->FreqL();
       
   356 								}
       
   357 
       
   358 							// Find the interval.
       
   359 							pos = FindRuleSegment(recRules, CICalRuleSegment::ESegInterval);
       
   360 							TInt interval = 1; //default value if no INTERVAL specified
       
   361 							if (pos != KErrNotFound)
       
   362 								{
       
   363 								ASSERT(recRules[pos]->Values().Count() >= 0);
       
   364 								interval = recRules[pos]->Values()[0]->IntegerL();
       
   365 								}
       
   366 						
       
   367 							if ((freq == CICalRuleSegment::EFreqYearly) && (interval == 1))
       
   368 								{
       
   369 								//Anniversary repeats once a year
       
   370 								eventType = CCalEntry::EAnniv;
       
   371 								}
       
   372 								
       
   373 							CleanupStack::PopAndDestroy(&recRules);
       
   374 							}
       
   375 						}
       
   376 					}
       
   377 				CleanupStack::Pop(entryUid);
       
   378 				// Passing ownership of entryUid
       
   379 				ImportEntryL(aCal, aComponent, aEntries, entryUid, eventType);
       
   380 				}
       
   381 				break;
       
   382 			case CICalBase::EICalTodo :
       
   383 				CleanupStack::Pop(entryUid);
       
   384 				// Passing ownership of entryUid
       
   385 				ImportEntryL(aCal, aComponent, aEntries, entryUid, CCalEntry::ETodo);
       
   386 				break;
       
   387 			case CICalBase::EICalJournal :
       
   388 				ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, *entryUid, KICalJournal, EFalse);
       
   389 				// Continue equates to skip in this instance.
       
   390 				break;
       
   391 			case CICalBase::EICalAlarm :
       
   392 				ReportErrorL(MAgnImportObserver::EImpErrorInvalidData, *entryUid, KICalAlarm, EFalse);
       
   393 				// Continue equates to skip in this instance.
       
   394 				break;
       
   395 			case CICalBase::EICalFreeBusy :
       
   396 				ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, *entryUid, KICalFreeBusy, EFalse);
       
   397 				// Continue equates to skip in this instance.
       
   398 				break;
       
   399 			case CICalBase::EICalInvalid :	// not valid here, fall through
       
   400 			case CICalBase::EICalCalendar :	// not valid here, fall through
       
   401 			case CICalBase::EICalTimeZone :	// not valid here, fall through
       
   402 			case CICalBase::EICalStandard :	// not valid here, fall through
       
   403 			case CICalBase::EICalDaylight :	// not valid here, fall through
       
   404 			default :
       
   405 				ReportErrorL( MAgnImportObserver::EImpErrorInvalidData,
       
   406 				              *entryUid,
       
   407 				              aComponent.TypeStringL(),
       
   408 				              EFalse );
       
   409 				// Continue equates to skip in this instance.
       
   410 				break;
       
   411 			}
       
   412 		}
       
   413 	TRACE_EXIT_POINT;
       
   414 	}
       
   415 
       
   416 /**
       
   417 Checks for a VALARM in a component. If a valid one is found, it is added to the
       
   418 specified entry.
       
   419 @param aComponent Component to search for a VALARM in.
       
   420 @param aEntry Alarm is added to this calendar entry.
       
   421 @param aUid UID of the component.
       
   422 @param aStartTime A pointer to the DTSTART of the parent component, if it has
       
   423 one, or NULL if it does not. This does not take ownership.
       
   424 @return MAgnImportObserver::TImpResponse indicating application response to errors, if any.
       
   425 @internalTechnology
       
   426 */
       
   427 void CAgnVersit2Importer::ImportAlarmL( const CICalComponent& aComponent,
       
   428                                         CCalEntry& aEntry,
       
   429                                         const HBufC8& aUid,
       
   430                                         const TCalTime* aStartTime )
       
   431 	{
       
   432 	TRACE_ENTRY_POINT;
       
   433 	
       
   434 	if (aComponent.ComponentExists(CICalBase::EICalAlarm))
       
   435 		{
       
   436 		// Check the outer component is a VEVENT or a VTODO
       
   437 		if (aComponent.Type() == CICalBase::EICalEvent || aComponent.Type() == CICalBase::EICalTodo)
       
   438 			{
       
   439 			const RPointerArray<CICalComponent>& nestedComponents = aComponent.Components();
       
   440 			// Iterate through all the nested components and create a new alarm for each VALARM component
       
   441 			TInt nestedComCount = nestedComponents.Count();
       
   442 			for (TInt i = 0; i < nestedComCount; i++)
       
   443 				{
       
   444 				if (nestedComponents[i]->Type() == CICalBase::EICalAlarm)
       
   445 					{
       
   446 					CCalAlarm* alarm = CCalAlarm::NewL();
       
   447 					CleanupStack::PushL(alarm);
       
   448 					const RPointerArray<CICalProperty>& nestedProperties = nestedComponents[i]->Properties();
       
   449 					// Go through all the nested properties until we find the TRIGGER
       
   450 					// Ignore REPEAT and DURATION + any others
       
   451 					TBool foundTrigger=EFalse;
       
   452 					TInt nestedPropCount = nestedProperties.Count();
       
   453 					for (TInt j = 0; j < nestedPropCount; j++)
       
   454 						{
       
   455 						if (nestedProperties[j]->Type() == KICalTrigger)
       
   456 							{
       
   457 							const RPointerArray<CICalValue>& values = nestedProperties[j]->Values();
       
   458 							// There should only be one value, don't try to add the alarm if there are more
       
   459 							if (values.Count() == 1)
       
   460 								{
       
   461 								const CICalPropertyParam* valueType = nestedProperties[j]->FindParam(KICalValue);
       
   462 								TTimeIntervalMinutes duration;
       
   463 								if (valueType) // Only DATE-TIME is legal here - assume it's that one.
       
   464 									{
       
   465 									if (!aStartTime)
       
   466 										{
       
   467 										ReportErrorL( MAgnImportObserver::EImpErrorMissingData,
       
   468 										              aUid,
       
   469 										              iStringProvider.StringL(EICalErrValarmNoStart),
       
   470 										              EFalse );
       
   471 										// On continue, we skip the alarm.
       
   472 										}
       
   473 									else
       
   474 										{
       
   475 										TCalTime absTime;
       
   476 										GetCalTimeL(*nestedProperties[j], absTime, EDateTime);
       
   477 										aStartTime->TimeUtcL().MinutesFrom(absTime.TimeUtcL(), duration);
       
   478 										}
       
   479 									}
       
   480 								else
       
   481 									{
       
   482 									duration = values[0]->DurationL().Int() / KSecondsInOneMinute;
       
   483 									}
       
   484 
       
   485 								// Only negative durations are allowed (the alarm must be *before* the event).
       
   486 								if (duration.Int() > 0)
       
   487 									{
       
   488 									ReportErrorL( MAgnImportObserver::EImpErrorNotSupported,
       
   489 									              aUid,
       
   490 									              iStringProvider.StringL(EICalErrAlarmAfterEvent) );
       
   491 									// On continue, the duration will be made "negative".
       
   492 									}
       
   493 
       
   494 								// Agenda expects a positive duration - convert the sign.
       
   495 								if (duration.Int() < 0)
       
   496 									{
       
   497 									duration = -(duration.Int());
       
   498 									}
       
   499 
       
   500 								alarm->SetTimeOffset(duration);
       
   501 								foundTrigger=ETrue;
       
   502 								}
       
   503 							}
       
   504 						}
       
   505 					if (foundTrigger)
       
   506 						{
       
   507 						aEntry.SetAlarmL(alarm);// Doesn't take ownership
       
   508 						}
       
   509 					else
       
   510 						{
       
   511 						ReportErrorL( MAgnImportObserver::EImpErrorMissingData,
       
   512 						              aUid,
       
   513 						              iStringProvider.StringL(EICalErrValarmNoTrigger),
       
   514 						              EFalse );
       
   515 						// On continue, the alarm will be skipped.
       
   516 						}
       
   517 					CleanupStack::PopAndDestroy(alarm);
       
   518 					}
       
   519 				}
       
   520 			}
       
   521 		else
       
   522 			{
       
   523 			ReportErrorL( MAgnImportObserver::EImpErrorInvalidData,
       
   524 			              aUid,
       
   525 			              iStringProvider.StringL(EICalErrValarmNotAllowed),
       
   526 			              EFalse );
       
   527 			// On continue, the alarm will be skipped.
       
   528 			}
       
   529 		}
       
   530 	
       
   531 	TRACE_EXIT_POINT;
       
   532 	}
       
   533 
       
   534 
       
   535 /**
       
   536 Performs most of the work of importing a component from an iCalendar, provided
       
   537 that the component is one which can be handled as a CCalEntry. Timezone and
       
   538 Alarm components are not imported in this manner.
       
   539 @param aCal The calendar object containing the component.
       
   540 @param aComponent The component to be imported.
       
   541 @param aEntries The array onto which to append the new entry.
       
   542 @param aUid The UID of the component (takes ownership).
       
   543 @param aType The type of entry being imoported
       
   544 @return MAgnImportObserver::TImpResponse indicating application response to errors, if any.
       
   545 @internalTechnology
       
   546 */
       
   547 void CAgnVersit2Importer::ImportEntryL( const CICal& aCal,
       
   548                                         const CICalComponent& aComponent,
       
   549                                         RPointerArray<CCalEntry>& aEntries,
       
   550                                         HBufC8* aUid,
       
   551                                         CCalEntry::TType aType )
       
   552 	{
       
   553 	TRACE_ENTRY_POINT;
       
   554 	
       
   555 	// Create a basic entry to add properties to.
       
   556 	CCalEntry* entry = CreateEntryLC(aCal, aComponent, aUid, aType); // takes ownership of aUid
       
   557 
       
   558 	iNeedsTzRules = (EFalse);
       
   559 	iCurrentTzRules = NULL;
       
   560 
       
   561 	// set the entry properties:
       
   562 	CICalProperty* rruleproperty = NULL;
       
   563 	CICalProperty* startproperty = NULL;
       
   564 	CICalProperty* endproperty = NULL;
       
   565 	CICalProperty* durationproperty = NULL;
       
   566 	RPointerArray<CICalProperty> exDateProperties;
       
   567 	CleanupClosePushL(exDateProperties);
       
   568 	RPointerArray<CICalProperty> rDateProperties;
       
   569 	CleanupClosePushL(rDateProperties);
       
   570 
       
   571 	const RPointerArray<CICalProperty>& properties = aComponent.Properties();
       
   572 	TInt propCount = properties.Count();
       
   573 	for (TInt pnum = 0; pnum < propCount; ++pnum)
       
   574 		{
       
   575 		CICalProperty* property = properties[pnum];
       
   576 
       
   577 		// DTSTART, DTEND, DURATION, EXDATE, RDATE and RRULE need special handling,
       
   578 		//as they affect one another.
       
   579 		if (property->Type().CompareF(KICalRRule) == 0)
       
   580 			{
       
   581 			rruleproperty = property;
       
   582 			}
       
   583 		else if (property->Type().CompareF(KICalDtstart) == 0)
       
   584 			{
       
   585 			startproperty = property;
       
   586 			}
       
   587 		else if (property->Type().CompareF(KICalDtend) == 0)
       
   588 			{
       
   589 			endproperty = property;
       
   590 			}
       
   591 		else if (property->Type().CompareF(KICalDuration) == 0)
       
   592 			{
       
   593 			durationproperty = property;
       
   594 			}
       
   595 		else if (property->Type().CompareF(KICalExdate) == 0)
       
   596 			{
       
   597 			// It is valid to have more than one EXDATE property. We store them all in an array.
       
   598 			User::LeaveIfError(exDateProperties.Append(property));
       
   599 			}
       
   600 		else if (property->Type().CompareF(KICalRdate) == 0)
       
   601 			{
       
   602 			// It is valid to have more than one RDATE property. We store them all in an array.
       
   603 			User::LeaveIfError(rDateProperties.Append(property));
       
   604 			}
       
   605 		else
       
   606 			{
       
   607 			ImportPropertyL(*entry, *property);
       
   608 			}
       
   609 		}
       
   610 
       
   611 	// We cannot handle a DTSTART, DTEND or DURATION field on its own, so we have saved them up
       
   612 	// and will sort them out here.
       
   613 	// In theory, some methods allow an event to specify an end time but no start time.
       
   614 	// We have no way of dealing with this so we discard it.  When we get a start time
       
   615 	// with no end time, we assume a duration of 0 seconds.
       
   616 	TCalTime start;
       
   617 	TCalTime end;
       
   618 	if (startproperty)
       
   619 		{
       
   620 		GetCalTimeL(*startproperty, start, EDateTime);
       
   621 		end = start;
       
   622 		if (endproperty)
       
   623 			{
       
   624 			GetCalTimeL(*endproperty, end, EDateTime);
       
   625 			}
       
   626 		else if (durationproperty && startproperty)
       
   627 			{
       
   628 			if (durationproperty->Values().Count() < 1)
       
   629 				{
       
   630 				ReportErrorL(MAgnImportObserver::EImpErrorMissingData, *aUid, KICalDuration);
       
   631 				// On continue use the start time as the end time (a duration of 0 seconds)
       
   632 				}
       
   633 			else
       
   634 				{
       
   635 				end.SetTimeUtcL(start.TimeUtcL() + durationproperty->Values()[0]->DurationL());
       
   636 				}
       
   637 			}
       
   638 		entry->SetStartAndEndTimeL(start, end);
       
   639 		}
       
   640 
       
   641 	// We must have a start time before we can interpret some alarms:
       
   642 	TRAPD(alarmerr, ImportAlarmL(aComponent, *entry, *aUid, startproperty?&start:0));
       
   643 	// If we fail and elect to skip whilst importing the alarm, continue
       
   644 	// with the current component.
       
   645 	if (alarmerr && iResponse == MAgnImportObserver::EImpResponseSkip)
       
   646 		{
       
   647 		iResponse = MAgnImportObserver::EImpResponseContinue;
       
   648 		}
       
   649 	else
       
   650 		{
       
   651 		User::LeaveIfError(alarmerr);
       
   652 		}
       
   653 
       
   654 	// We cannot put an rrule property into the agenda model format until we
       
   655 	// have properties such as dtstart already stored, so we do this last:
       
   656 	if (rruleproperty)
       
   657 		{
       
   658 		if (startproperty)
       
   659 			{
       
   660 			if (ImportRRuleL(*rruleproperty, *entry, start))
       
   661 				{
       
   662 				// APINOTE: In the Cal Interim API EXDATE is only valid with an RRULE.
       
   663 				// This is not necessarily so for iTIP updates.
       
   664 				for (TInt i = 0; i < exDateProperties.Count(); i++)
       
   665 					{
       
   666 					ImportPropertyL(*entry, *(exDateProperties[i]));
       
   667 					}
       
   668 				}
       
   669 			else if (exDateProperties.Count() > 0)
       
   670 				{
       
   671 				// Cannot process an EXDATE without an RRULE.
       
   672 				ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, *aUid, KICalExdate);
       
   673 				}
       
   674 			}
       
   675 		else
       
   676 			{
       
   677 			// Cannot process an RRULE without a DTSTART
       
   678 			ReportErrorL(MAgnImportObserver::EImpErrorMissingData, *aUid, KICalDtstart);
       
   679 			}
       
   680 		}
       
   681 
       
   682 
       
   683 	// RDATE does not neccessary need an RRULE.
       
   684 	for (TInt i = 0; i < rDateProperties.Count(); i++)
       
   685 		{
       
   686 		ImportPropertyL(*entry, *(rDateProperties[i]));
       
   687 		}
       
   688 
       
   689 	CleanupStack::PopAndDestroy(&rDateProperties);
       
   690 	CleanupStack::PopAndDestroy(&exDateProperties);
       
   691 
       
   692 	// APINOTE: When setting the RRULE, the API overwrites the DTEND field.
       
   693 	// This block sets it back to what it should be.
       
   694 	if (startproperty)
       
   695 		{
       
   696 		// We don't need to check for an end time as it gets initialised when the
       
   697 		// start time gets set.
       
   698 		entry->SetStartAndEndTimeL(start, end);
       
   699 		}
       
   700 
       
   701 	// If we have set up a timezone, add this to the entry.
       
   702 	// Only entries with RDATES, EXDATES, RRULES or EXRULES will have this.
       
   703 	if (iNeedsTzRules)
       
   704 		{
       
   705 		if (iCurrentTzRules)
       
   706 			{
       
   707 			entry->SetTzRulesL(*iCurrentTzRules);
       
   708 			}
       
   709 		}
       
   710 
       
   711 	//Set the last modified date to current time
       
   712 	entry->SetLastModifiedDateL();
       
   713 	// Store the entry:
       
   714 	User::LeaveIfError(aEntries.Append(entry)); // Takes ownership if successful
       
   715 	CleanupStack::Pop(entry);
       
   716 	
       
   717 	TRACE_EXIT_POINT;
       
   718 	}
       
   719 
       
   720 /**
       
   721 Creates a new entry and pushes it onto the cleanup stack.
       
   722 @param aCal The calendar object containing the component.
       
   723 @param aComponent The component to be imported.
       
   724 @param aUid The UID of the component (takes ownership).
       
   725 @param aType The type of entry being imoported
       
   726 @return A new CCalEntry, or zero if a recoverable error occurs and the observer
       
   727 elects not to continue from it.
       
   728 @internalTechnology
       
   729 */
       
   730 CCalEntry * CAgnVersit2Importer::CreateEntryLC( const CICal& aCal,
       
   731                                                 const CICalComponent& aComponent,
       
   732                                                 HBufC8* aUid,
       
   733                                                 CCalEntry::TType aType )
       
   734     {
       
   735     TRACE_ENTRY_POINT;
       
   736     
       
   737 	CleanupStack::PushL(aUid);
       
   738 
       
   739 	const CICalProperty* propSeq = aComponent.FindProperty(KICalSequence);
       
   740 
       
   741 	// Find the sequence number, but accept a default of 0 if there isn't one:
       
   742 	TUint entrySeq = 0;
       
   743 	if (propSeq && propSeq->Values().Count() > 0)
       
   744 		{
       
   745 		entrySeq = propSeq->Values()[0]->IntegerL();
       
   746 		}
       
   747 
       
   748 	// Find the method, but accept a default of EMethodNone if there isn't one:
       
   749 	CCalEntry::TMethod method = CCalEntry::EMethodNone;
       
   750 	const CICalProperty* prop = aCal.FindProperty(KICalMethod);
       
   751 	if (prop && prop->Values().Count() > 0)
       
   752 		{
       
   753 		TPtrC val;
       
   754 		val.Set(prop->Values()[0]->TextL());
       
   755 		if (val.CompareF(KICalPublish) == 0)
       
   756 			{
       
   757 			method = CCalEntry::EMethodPublish;
       
   758 			}
       
   759 		else if (val.CompareF(KICalRequest) == 0)
       
   760 			{
       
   761 			method = CCalEntry::EMethodRequest;
       
   762 			}
       
   763 		else if (val.CompareF(KICalReply) == 0)
       
   764 			{
       
   765 			method = CCalEntry::EMethodReply;
       
   766 			}
       
   767 		else if (val.CompareF(KICalAdd) == 0)
       
   768 			{
       
   769 			method = CCalEntry::EMethodAdd;
       
   770 			}
       
   771 		else if (val.CompareF(KICalCancel) == 0)
       
   772 			{
       
   773 			method = CCalEntry::EMethodCancel;
       
   774 			}
       
   775 		else if (val.CompareF(KICalRefresh) == 0)
       
   776 			{
       
   777 			method = CCalEntry::EMethodRefresh;
       
   778 			}
       
   779 		else if (val.CompareF(KICalCounter) == 0)
       
   780 			{
       
   781 			method = CCalEntry::EMethodCounter;
       
   782 			}
       
   783 		else if (val.CompareF(KICalDeclineCounter) == 0)
       
   784 			{
       
   785 			method = CCalEntry::EMethodDeclineCounter;
       
   786 			}
       
   787 		else
       
   788 			{
       
   789 			ReportErrorL(MAgnImportObserver::EImpErrorInvalidData, *aUid, val);
       
   790 			// On continue, use EMethodNone.
       
   791 			}
       
   792 		}
       
   793 
       
   794 	CCalEntry* entry = NULL;
       
   795 	// Find the recurrence information, if there is any:
       
   796 	const CICalProperty* propRecurrenceId = aComponent.FindProperty(KICalRecurrenceId);
       
   797 	if (propRecurrenceId)
       
   798 		{
       
   799 		TCalTime entryRecId;
       
   800 		GetCalTimeL(*propRecurrenceId, entryRecId, EDateTime);
       
   801 
       
   802 		const CICalPropertyParam* range = propRecurrenceId->FindParam(KICalRange);
       
   803 		CalCommon::TRecurrenceRange entryRange = CalCommon::EThisOnly;
       
   804 		if (range && range->Values().Count() > 0)
       
   805 			{
       
   806 			if (range->Values()[0]->TextL().CompareF(KICalThisAndPrior) == 0)
       
   807 				{
       
   808 				entryRange = CalCommon::EThisAndPrior;
       
   809 				}
       
   810 			else if (range->Values()[0]->TextL().CompareF(KICalThisAndFuture) == 0)
       
   811 				{
       
   812 				entryRange = CalCommon::EThisAndFuture;
       
   813 				}
       
   814 			else
       
   815 				{
       
   816 				ReportErrorL(MAgnImportObserver::EImpErrorInvalidData, *aUid, range->Values()[0]->TextL());
       
   817 				// On continue, assume this instance only.
       
   818 				}
       
   819 			}
       
   820 		// Create an entry with recurrence data:
       
   821 		// Passing ownership of aUid
       
   822 		CleanupStack::Pop(aUid);
       
   823 		entry = CCalEntry::NewL(aType, aUid, method, entrySeq, entryRecId, entryRange);
       
   824 		CleanupStack::PushL(entry);
       
   825 		}
       
   826 	else
       
   827 		{
       
   828 		// Create an entry without recurrence data:
       
   829 		// Passing ownership of aUid
       
   830 		CleanupStack::Pop(aUid);
       
   831 		entry = CCalEntry::NewL(aType, aUid, method, entrySeq);
       
   832 		CleanupStack::PushL(entry);
       
   833 		}
       
   834     
       
   835     TRACE_EXIT_POINT;
       
   836 	return entry;
       
   837 	}
       
   838 
       
   839 /**
       
   840 Imports an individual property and adds it to an entry.
       
   841 @param aEntry The entry to which the property is to be added.
       
   842 @param aProperty The property to add.
       
   843 @internalTechnology
       
   844 */
       
   845 void CAgnVersit2Importer::ImportPropertyL(CCalEntry& aEntry, const CICalProperty& aProperty)
       
   846 	{
       
   847 	TRACE_ENTRY_POINT;
       
   848 	
       
   849 	if (aProperty.Type().CompareF(KICalAttendee) == 0)
       
   850 		{
       
   851 		// Find the paramaters we need:
       
   852 		CICalValue* address = aProperty.Values()[0];
       
   853 		const CICalPropertyParam* sentBy = aProperty.FindParam(KICalSentBy);
       
   854 		const CICalPropertyParam* role = aProperty.FindParam(KICalRole);
       
   855 		const CICalPropertyParam* status = aProperty.FindParam(KICalPartStat);
       
   856 		const CICalPropertyParam* rsvp = aProperty.FindParam(KICalRsvp);
       
   857 		const CICalPropertyParam* cn = aProperty.FindParam(KICalCn);
       
   858 		// The role:
       
   859 		CCalAttendee::TCalRole roleVal = CCalAttendee::EReqParticipant;
       
   860 		if (role && role->Values().Count() > 0)
       
   861 			{
       
   862 			CICalValue* theVal = role->Values()[0];
       
   863 			if (theVal->TextL().CompareF(KICalChair) == 0)
       
   864 				{
       
   865 				roleVal = CCalAttendee::EChair;
       
   866 				}
       
   867 			else if (theVal->TextL().CompareF(KICalOptParticipant) == 0)
       
   868 				{
       
   869 				roleVal = CCalAttendee::EOptParticipant;
       
   870 				}
       
   871 			else if (theVal->TextL().CompareF(KICalNonParticipant) == 0)
       
   872 				{
       
   873 				roleVal = CCalAttendee::ENonParticipant;
       
   874 				}
       
   875 
       
   876 			}
       
   877 		// The status:
       
   878 		CCalAttendee::TCalStatus statusVal = CCalAttendee::ENeedsAction;
       
   879 		if (status && status->Values().Count() > 0)
       
   880 			{
       
   881 			CICalValue* theVal = status->Values()[0];
       
   882 			if (theVal->TextL().CompareF(KICalAccepted) == 0)
       
   883 				{
       
   884 				statusVal = CCalAttendee::EAccepted;
       
   885 				}
       
   886 			else if (theVal->TextL().CompareF(KICalDeclined) == 0)
       
   887 				{
       
   888 				statusVal = CCalAttendee::EDeclined;
       
   889 				}
       
   890 			else if (theVal->TextL().CompareF(KICalTentative) == 0)
       
   891 				{
       
   892 				statusVal = CCalAttendee::ETentative;
       
   893 				}
       
   894 			else if (theVal->TextL().CompareF(KICalDelegated) == 0)
       
   895 				{
       
   896 				statusVal = CCalAttendee::EDelegated;
       
   897 				}
       
   898 			else if (theVal->TextL().CompareF(KICalCompleted) == 0)
       
   899 				{
       
   900 				statusVal = CCalAttendee::ECompleted;
       
   901 				}
       
   902 			else if (theVal->TextL().CompareF(KICalInProcess) == 0)
       
   903 				{
       
   904 				statusVal = CCalAttendee::EInProcess;
       
   905 				}
       
   906 			}
       
   907 		// The RSVP:
       
   908 		TBool rsvpVal = EFalse;
       
   909 		if (rsvp && rsvp->Values().Count() > 0)
       
   910 			{
       
   911 			rsvpVal = rsvp->Values()[0]->BooleanL();
       
   912 			}
       
   913 
       
   914 		// The complete attendee:
       
   915 		CCalAttendee* attendee;
       
   916 		if (sentBy && sentBy->Values().Count() > 0)
       
   917 			{
       
   918 			attendee = CCalAttendee::NewL(address->TextL(), sentBy->Values()[0]->TextL());
       
   919 			}
       
   920 		else
       
   921 			{
       
   922 			attendee = CCalAttendee::NewL(address->TextL());
       
   923 			}
       
   924 		CleanupStack::PushL(attendee);
       
   925 		if (cn && cn->Values().Count() > 0)
       
   926 			{
       
   927 			attendee->SetCommonNameL(cn->Values()[0]->TextL());
       
   928 			}
       
   929 		attendee->SetRoleL(roleVal);
       
   930 		attendee->SetStatusL(statusVal);
       
   931 		attendee->SetResponseRequested(rsvpVal);
       
   932 		// Add the attendee:
       
   933 		CleanupStack::Pop(attendee);
       
   934 		// Passing ownership of attendee
       
   935 		aEntry.AddAttendeeL(attendee);
       
   936 		}
       
   937 	else if (aProperty.Type().CompareF(KICalCategories) == 0)
       
   938 		{
       
   939 		ImportCategoriesL(aProperty, aEntry);
       
   940 		}
       
   941 	else if (aProperty.Type().CompareF(KICalClass) == 0)
       
   942 		{
       
   943 		ImportClassL(aProperty, aEntry);
       
   944 		}
       
   945 	else if (aProperty.Type().CompareF(KICalDescription) == 0)
       
   946 		{
       
   947 		if (aProperty.Values().Count() < 1)
       
   948 			{
       
   949 			ReportErrorL(MAgnImportObserver::EImpErrorMissingData, aEntry.UidL(), KICalDescription);
       
   950 			// On continue ignore the description.
       
   951 			}
       
   952 		else
       
   953 			{
       
   954 			aEntry.SetDescriptionL(aProperty.Values()[0]->TextL());
       
   955 			}
       
   956 		}
       
   957 	else if (aProperty.Type().CompareF(KICalLocation) == 0)
       
   958 		{
       
   959 		// CCalEntry only supports one location, so bundle them all
       
   960 		// together into one descriptor.
       
   961 		TInt numLocations = aProperty.Values().Count();
       
   962 
       
   963 		if (numLocations > 0)
       
   964 			{
       
   965 			HBufC* loc (aProperty.Values()[0]->TextL().AllocLC());
       
   966 
       
   967 			for (TInt i = 1; i < numLocations; i++)
       
   968 				{
       
   969 				HBufC* oldLoc = loc;
       
   970 				loc = loc->ReAllocL(loc->Length() + aProperty.Values()[i]->TextL().Length() + 1);
       
   971 				CleanupStack::Pop(oldLoc); // location of loc has changed, cleanupstack needs updating
       
   972 				CleanupStack::PushL(loc);
       
   973 				loc->Des().Append(KICalComma);
       
   974 				loc->Des().Append(aProperty.Values()[i]->TextL());
       
   975 				}
       
   976 
       
   977 			aEntry.SetLocationL(*loc);
       
   978 			CleanupStack::PopAndDestroy(loc);
       
   979 			}
       
   980 		}
       
   981 	else if (aProperty.Type().CompareF(KICalOrganizer) == 0)
       
   982 		{
       
   983 		if (aProperty.Values().Count() < 1)
       
   984 			{
       
   985 			ReportErrorL(MAgnImportObserver::EImpErrorMissingData, aEntry.UidL(), KICalOrganizer);
       
   986 			// On continue ignore the organizer.
       
   987 			}
       
   988 		else
       
   989 			{
       
   990 			CICalValue* address = aProperty.Values()[0];
       
   991 			const CICalPropertyParam* sentBy = aProperty.FindParam(KICalSentBy);
       
   992 			const CICalPropertyParam* cn = aProperty.FindParam(KICalCn);
       
   993 			CCalUser* user = NULL;
       
   994 			if (sentBy && sentBy->Values().Count() > 0)
       
   995 				{
       
   996 				user = CCalAttendee::NewL(address->TextL(), sentBy->Values()[0]->TextL());
       
   997 				}
       
   998 			else
       
   999 				{
       
  1000 				user = CCalAttendee::NewL(address->TextL());
       
  1001 				}
       
  1002 			CleanupStack::PushL(user);
       
  1003 			if (cn && cn->Values().Count() > 0)
       
  1004 				{
       
  1005 				user->SetCommonNameL(cn->Values()[0]->TextL());
       
  1006 				}
       
  1007 			CleanupStack::Pop(user);
       
  1008 			// Passing ownership of user
       
  1009 			aEntry.SetOrganizerL(user);
       
  1010 			}
       
  1011 		}
       
  1012 	else if (aProperty.Type().CompareF(KICalRdate) == 0)
       
  1013 		{
       
  1014 		iNeedsTzRules = ETrue;
       
  1015 		RArray<TCalTime> dates;
       
  1016 		CleanupClosePushL(dates);
       
  1017 		aEntry.GetRDatesL(dates);
       
  1018 		TInt valCount = aProperty.Values().Count();
       
  1019 		for (TInt dnum = 0; dnum < valCount; ++dnum)
       
  1020 			{
       
  1021 			TCalTime time;
       
  1022 			GetCalTimeL(aProperty, time, EDateTime, dnum);
       
  1023 			User::LeaveIfError(dates.Append(time));
       
  1024 			}
       
  1025 		aEntry.SetRDatesL(dates);
       
  1026 		CleanupStack::PopAndDestroy(&dates);
       
  1027 		}
       
  1028 	else if (aProperty.Type().CompareF(KICalExdate) == 0)
       
  1029 		{
       
  1030 		iNeedsTzRules = ETrue;
       
  1031 		RArray<TCalTime> dates;
       
  1032 		CleanupClosePushL(dates);
       
  1033 		aEntry.GetExceptionDatesL(dates);
       
  1034 		TInt valCount = aProperty.Values().Count();
       
  1035 		for (TInt dnum = 0; dnum < valCount; ++dnum)
       
  1036 			{
       
  1037 			TCalTime time;
       
  1038 			GetCalTimeL(aProperty, time, EDateTime, dnum);
       
  1039 			User::LeaveIfError(dates.Append(time));
       
  1040 			}
       
  1041 		aEntry.SetExceptionDatesL(dates);
       
  1042 		CleanupStack::PopAndDestroy(&dates);
       
  1043 		}
       
  1044 	else if (aProperty.Type().CompareF(KICalStatus) == 0)
       
  1045 		{
       
  1046 		if (aProperty.Values().Count() < 1)
       
  1047 			{
       
  1048 			ReportErrorL(MAgnImportObserver::EImpErrorMissingData, aEntry.UidL(), KICalDescription);
       
  1049 			// On continue ignore the status.
       
  1050 			}
       
  1051 		else
       
  1052 			{
       
  1053 			TPtrC statstr(aProperty.Values()[0]->TextL());
       
  1054 			if (statstr.CompareF(KICalTentative) == 0)
       
  1055 				{
       
  1056 				aEntry.SetStatusL(CCalEntry::ETentative);
       
  1057 				}
       
  1058 			else if (statstr.CompareF(KICalConfirmed) == 0)
       
  1059 				{
       
  1060 				aEntry.SetStatusL(CCalEntry::EConfirmed);
       
  1061 				}
       
  1062 			else if (statstr.CompareF(KICalCancelled) == 0)
       
  1063 				{
       
  1064 				aEntry.SetStatusL(CCalEntry::ECancelled);
       
  1065 				}
       
  1066 			else if (statstr.CompareF(KICalNeedsAction) == 0)
       
  1067 				{
       
  1068 				aEntry.SetStatusL(CCalEntry::ETodoNeedsAction);
       
  1069 				}
       
  1070 			else if (statstr.CompareF(KICalCompleted) == 0)
       
  1071 				{
       
  1072 				aEntry.SetStatusL(CCalEntry::ETodoCompleted);
       
  1073 				}
       
  1074 			else if (statstr.CompareF(KICalInProcess) == 0)
       
  1075 				{
       
  1076 				aEntry.SetStatusL(CCalEntry::ETodoInProcess);
       
  1077 				}
       
  1078 			else
       
  1079 				{
       
  1080 				ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, aEntry.UidL(), statstr);
       
  1081 				// On continue ignore the status.
       
  1082 				}
       
  1083 			}
       
  1084 		}
       
  1085 	else if (aProperty.Type().CompareF(KICalSummary) == 0)
       
  1086 		{
       
  1087 		if (aProperty.Values().Count() < 1)
       
  1088 			{
       
  1089 			ReportErrorL(MAgnImportObserver::EImpErrorMissingData, aEntry.UidL(), KICalDescription);
       
  1090 			// On continue ignore the summary.
       
  1091 			}
       
  1092 		else
       
  1093 			{
       
  1094 			aEntry.SetSummaryL(aProperty.Values()[0]->TextL());
       
  1095 			}
       
  1096 		}
       
  1097 	else if (aProperty.Type().CompareF(KICalPriority) == 0)
       
  1098 		{
       
  1099 		if (aProperty.Values().Count() < 1)
       
  1100 			{
       
  1101 			ReportErrorL(MAgnImportObserver::EImpErrorMissingData, aEntry.UidL(), KICalDescription);
       
  1102 			// On continue ignore the priority.
       
  1103 			}
       
  1104 		else
       
  1105 			{
       
  1106 			TInt priority = aProperty.Values()[0]->IntegerL();
       
  1107 			
       
  1108 		    //Pirorites are saved always in vcal format
       
  1109 		    //so they are mapped the following way
       
  1110 		    //iCal 1 - 4 = vCal 1
       
  1111 		    //iCal 5     = vCal 2
       
  1112 		    //iCal 6 - 9 = vCal 3
       
  1113 			if( priority < 5 )
       
  1114 			    {
       
  1115 			    priority = 1;
       
  1116 			    }
       
  1117 			
       
  1118 			else if( priority == 5 )
       
  1119 			    {
       
  1120 			    priority = 2;
       
  1121 			    }
       
  1122 			
       
  1123 			else 
       
  1124 			    {
       
  1125 			    priority = 3;
       
  1126 			    }
       
  1127 			    
       
  1128 			aEntry.SetPriorityL( priority );
       
  1129 			}
       
  1130 		}
       
  1131 
       
  1132 	else if (aProperty.Type().CompareF(KICalDtstamp) == 0)
       
  1133 		{
       
  1134 		TCalTime timeStamp;
       
  1135 		GetCalTimeL(aProperty, timeStamp, EDateTime);
       
  1136 		aEntry.SetDTStampL(timeStamp);
       
  1137 		}
       
  1138 	else if ((aProperty.Type().CompareF(KICalUid) == 0) ||
       
  1139 			 (aProperty.Type().CompareF(KICalSequence) == 0) ||
       
  1140 			 (aProperty.Type().CompareF(KICalRecurrenceId) == 0) ||
       
  1141 			 (aProperty.Type().CompareF(KICalLastmodified) == 0))
       
  1142 		{
       
  1143 		//Already been handled when constructing the entry :- do nothing
       
  1144 		}
       
  1145 	else if (aProperty.Type().Find(KICalXProperty) == 0)
       
  1146 		{
       
  1147 		// Quietly swallow X- properties, instead of reporting "NotSupported"
       
  1148 		}
       
  1149 	else if (aProperty.Type().Find(KICalGeo) == 0)
       
  1150 	    {
       
  1151 	    //Extract Geo co-ordinates latitude and longitude values from property
       
  1152 	   
       
  1153 	    TInt valCount = aProperty.Values().Count();  
       
  1154 	    if(valCount > 0 && valCount < 2)
       
  1155 	        {
       
  1156 	        HBufC* geoBuffLatLong (aProperty.Values()[0]->TextL().AllocLC());
       
  1157 	        // Determine the position of the delimiter for extraction of the geo latitude and longitude values
       
  1158 	        TInt delimiterPos = geoBuffLatLong->Locate(KAgnVersitTokenSemiColonVal);
       
  1159 	        
       
  1160 	        if(delimiterPos!=KErrNotFound)
       
  1161                 {
       
  1162                 // Extract the latitude
       
  1163                 TLex geoLatitudeLex(geoBuffLatLong->Left(delimiterPos));
       
  1164                 // Extract the longitude by excluding the delimiter
       
  1165                 TLex geoLongitudeLex(geoBuffLatLong->Right(geoBuffLatLong->Length()-(delimiterPos+1)));
       
  1166                 
       
  1167                 TReal geoLatitude;
       
  1168                 TReal geoLongitude;
       
  1169                 
       
  1170                 if((geoLatitudeLex.Val(geoLatitude)==KErrNone) && (geoLongitudeLex.Val(geoLongitude)==KErrNone))
       
  1171                     {
       
  1172                     CCalGeoValue* importedGeoValue=CCalGeoValue::NewL();
       
  1173                     CleanupStack::PushL(importedGeoValue);
       
  1174                     TRAPD(err, importedGeoValue->SetLatLongL(geoLatitude,geoLongitude));
       
  1175                     if(err==KErrNone)
       
  1176                         {
       
  1177                         aEntry.SetGeoValueL(*importedGeoValue);
       
  1178                         }
       
  1179                     CleanupStack::PopAndDestroy(importedGeoValue);
       
  1180                     }
       
  1181                 }
       
  1182 	        CleanupStack::PopAndDestroy(geoBuffLatLong);
       
  1183 	        }
       
  1184 	    }
       
  1185 	else
       
  1186 		{
       
  1187 		ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, aEntry.UidL(), aProperty.Type());
       
  1188 		}
       
  1189 	
       
  1190 	TRACE_EXIT_POINT;
       
  1191 	}
       
  1192 
       
  1193 /**
       
  1194 Performs most of the work of importing a timezone component. Timezones are not
       
  1195 stored as separate entities within Agenda, but as CTzRules objects within
       
  1196 individual entries, and so this maintains an array of all timezone components
       
  1197 for any given calendar, to be accessed later as required.
       
  1198 @param aTimezone The timezone to convert into CTzRules format.
       
  1199 @return MAgnImportObserver::TImpResponse indicating application response to errors, if any.
       
  1200 @internalTechnology
       
  1201 */
       
  1202 void CAgnVersit2Importer::ImportTimezoneL(const CICalComponent& aTimezone)
       
  1203 	{
       
  1204 	TRACE_ENTRY_POINT;
       
  1205 	
       
  1206 	CTzRules* rules = NULL;
       
  1207 	// Get the TZID:
       
  1208 	TPtrC tzid;
       
  1209 	const CICalProperty* propUid = aTimezone.FindProperty(KICalTzid());
       
  1210 	if (propUid && propUid->Values().Count() > 0)
       
  1211 		{
       
  1212 		tzid.Set(propUid->Values()[0]->TextL());
       
  1213 		}
       
  1214 	else
       
  1215 		{
       
  1216 		ReportErrorL(MAgnImportObserver::EImpErrorInvalidData, KNullDesC8, KICalUid, EFalse);
       
  1217 		// A Timezone with no ID is completely pointless, so on continue skip.
       
  1218 		}
       
  1219 
       
  1220 	// Create somewhere to store the data we are parsing:
       
  1221 	rules = CTzRules::NewL();
       
  1222 	CleanupStack::PushL(rules);
       
  1223 
       
  1224 	// We don't care about any of the timezones properties except the tzid - we go straight
       
  1225 	// onto the standard and daylight values.
       
  1226 	const RPointerArray<CICalComponent>& tzComponents = aTimezone.Components();
       
  1227 	if (tzComponents.Count() < 1)
       
  1228 		{
       
  1229 		ReportErrorL(MAgnImportObserver::EImpErrorMissingData, KNullDesC8, KICalTimeZone, EFalse);
       
  1230 		// A Timezone without atleast 1 value is meaningless so on continue skip.
       
  1231 		}
       
  1232 	else
       
  1233 		{
       
  1234 		// Agenda expects a set of month+day definitions, which repeat every year between start and end years.
       
  1235 		// iCalendar provides a set of year+month+day definitions, which cannot always be represented.
       
  1236 		// We will try, and hope for the best, using the first rules start and end to define the overall duration,
       
  1237 		// effectively overwriting all the other rules.
       
  1238 		rules->SetInitialStdTimeOffset(0);
       
  1239 
       
  1240 		TInt tzCount = tzComponents.Count();
       
  1241 		for (TInt tznum = 0; tznum < tzCount; ++tznum)
       
  1242 			{
       
  1243 			// Find the properties for this component:
       
  1244 			CICalComponent* tzinterval = tzComponents[tznum];
       
  1245 			ImportTimezoneIntervalL(*tzinterval, *rules);
       
  1246 			}
       
  1247 		}
       
  1248 
       
  1249 	CTzNamedRules* namedRules = new (ELeave) CTzNamedRules;
       
  1250 	CleanupStack::Pop(rules);
       
  1251 	namedRules->iRules = rules;
       
  1252 	CleanupStack::PushL(namedRules);
       
  1253 	namedRules->iName = tzid.AllocL();
       
  1254 	User::LeaveIfError(iTzRules.Append(namedRules));
       
  1255 	CleanupStack::Pop(namedRules);
       
  1256 	
       
  1257 	TRACE_EXIT_POINT;
       
  1258 	}
       
  1259 
       
  1260 /**
       
  1261 Performs most of the work of translating a DAYLIGHT or STANDARD section of a
       
  1262 VTIMEZONE into the equivalent TTzRule for Agenda.
       
  1263 @param aInterval The DAYLIGHT or STANDARD component.
       
  1264 @param aRules The CTzRules into which the TTzRule will be placed.
       
  1265 @internalTechnology
       
  1266 */
       
  1267 void CAgnVersit2Importer::ImportTimezoneIntervalL( const CICalComponent& aInterval,
       
  1268                                                    CTzRules& aRules )
       
  1269 	{
       
  1270 	TRACE_ENTRY_POINT;
       
  1271 	
       
  1272 	// Find the properties:
       
  1273 	const CICalProperty* from = aInterval.FindProperty(KICalTzoffsetfrom);
       
  1274 	const CICalProperty* to = aInterval.FindProperty(KICalTzoffsetto);
       
  1275 	const CICalProperty* start = aInterval.FindProperty(KICalDtstart);
       
  1276 	const CICalProperty* rdate = aInterval.FindProperty(KICalRdate);
       
  1277 	const CICalProperty* rrule = aInterval.FindProperty(KICalRRule);
       
  1278 
       
  1279 	// Set the time offsets it implies:
       
  1280 	TTzRule tzrule;
       
  1281 	tzrule.iOldLocalTimeOffset = from->Values()[0]->UtcOffsetL().Int() / KSecondsInOneMinute;
       
  1282 	tzrule.iNewLocalTimeOffset = to->Values()[0]->UtcOffsetL().Int() / KSecondsInOneMinute;
       
  1283 	tzrule.iTimeReference = ETzUtcTimeReference;
       
  1284 
       
  1285 	RPointerArray<CICalRuleSegment> recRules;
       
  1286 	CleanupPointerArrayPushL(recRules);
       
  1287 
       
  1288 	// If this has an rdate with more than one value we can only represent it by
       
  1289 	// creating a seperate tzrule for each date.  Not only that, but because the rdate
       
  1290 	// specifies years, we need separate CTzRules for each year, which we can't actually
       
  1291 	// do in Agenda. This is unsupported.
       
  1292 	if (rdate)
       
  1293 		{
       
  1294 		ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8, KICalRdate);
       
  1295 		// On continue we ignore the rdate.
       
  1296 		}
       
  1297 
       
  1298 	// Start date
       
  1299 	// Agenda has a start year and end year for the entire timezone.
       
  1300 	// iCalendar has a start date for each interval and an end date for each rrule within the interval.
       
  1301 	// This means we are trying to map N starts and M ends to 1 start and 1 end.
       
  1302 	// We will just use whatever we find - it's not going to work and it can't be made to work.
       
  1303 	TDateTime dateTime;
       
  1304 	if (start)
       
  1305 		{
       
  1306 		TTime startTime;
       
  1307 		CICalValue::TTimeZoneType type;
       
  1308 		start->Values()[0]->GetDateTimeL(startTime, type);
       
  1309 		dateTime = startTime.DateTime();
       
  1310 		aRules.SetStartYear(dateTime.Year());
       
  1311 		tzrule.iFrom = dateTime;
       
  1312 		// We cannot set the day of the month on which this timezone rule starts being applied
       
  1313 		// because Agenda does not support it. We just have to make do without it; the field
       
  1314 		// gets set to the first day of the month by default.
       
  1315 		}
       
  1316 	else
       
  1317 		{
       
  1318 		ReportErrorL(MAgnImportObserver::EImpErrorMissingData, KNullDesC8, KICalDtstart, EFalse);
       
  1319 		// We cannot continue without a start, so skip.
       
  1320 		}
       
  1321 
       
  1322 	// If this has an rrule we may be able to represent it.
       
  1323 	if (rrule && rrule->Values().Count() > 0)
       
  1324 		{
       
  1325 		// One thing we cannot do is handle multiple RRules.
       
  1326 		if (rrule->Values().Count() > 1)
       
  1327 			{
       
  1328 			ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8,
       
  1329 						iStringProvider.StringL(EICalErrRruleNumRules));
       
  1330 			// On continue ignore all but the first RRule.
       
  1331 			}
       
  1332 		CICalRuleSegment::TFreq freq;
       
  1333 		rrule->Values()[0]->GetRecurrenceRuleL(recRules);
       
  1334 
       
  1335 		// Find the frequency first - if there is no frequency it is an error, and if the
       
  1336 		// frequency is anything other than yearly we can't handle it anyway.
       
  1337 		TInt pos = FindRuleSegment(recRules, CICalRuleSegment::ESegFreq);
       
  1338 		if (pos != KErrNotFound)
       
  1339 			{
       
  1340 			ASSERT(recRules.Count() >= pos + 1);
       
  1341 			freq = recRules[pos]->FreqL();
       
  1342 			if (freq != CICalRuleSegment::EFreqYearly)
       
  1343 				{
       
  1344 				ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8,
       
  1345 						iStringProvider.StringL(EICalErrRruleNotYearly));
       
  1346 				// On continue assume yearly.
       
  1347 				freq = CICalRuleSegment::EFreqYearly;
       
  1348 				}
       
  1349 			}
       
  1350 		else
       
  1351 			{
       
  1352 			ReportErrorL(MAgnImportObserver::EImpErrorMissingData, KNullDesC8,
       
  1353 						rrule->Values()[0]->TextL());
       
  1354 			// On continue assume yearly.
       
  1355 			freq = CICalRuleSegment::EFreqYearly;
       
  1356 			}
       
  1357 
       
  1358 		// Find the interval.  We can only handle an interval of 1.
       
  1359 		TInt thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegInterval);
       
  1360 		if (thePos != KErrNotFound)
       
  1361 			{
       
  1362 			ASSERT(recRules.Count() >= thePos + 1);
       
  1363 			ASSERT(recRules[thePos]->Values().Count() >= 0);
       
  1364 			if (recRules[thePos]->Values()[0]->IntegerL() != 1)
       
  1365 				{
       
  1366 				ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8, KICalInterval);
       
  1367 				// On continue assume the interval is 1.
       
  1368 				}
       
  1369 			}
       
  1370 
       
  1371 		// Find the count, and interpret it as an end year.
       
  1372 		// See the comment above about start date for the problems with this.
       
  1373 		thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegCount);
       
  1374 		if (thePos != KErrNotFound)
       
  1375 			{
       
  1376 			ASSERT(recRules.Count() >= thePos + 1);
       
  1377 			ASSERT(recRules[thePos]->Values().Count() >= 0);
       
  1378 			TInt count = recRules[thePos]->Values()[0]->IntegerL();
       
  1379 			aRules.SetEndYear(aRules.StartYear() + count);
       
  1380 			}
       
  1381 
       
  1382 		// Find the until, and interpret it as an end year.
       
  1383 		// See the comment above about start date for the problems with this.
       
  1384 		thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegUntil);
       
  1385 		if (thePos != KErrNotFound)
       
  1386 			{
       
  1387 			ASSERT(recRules.Count() >= thePos + 1);
       
  1388 			ASSERT(recRules[thePos]->Values().Count() >= 0);
       
  1389 			TTime endTime;
       
  1390 			recRules[thePos]->Values()[0]->GetDateL(endTime);
       
  1391 			aRules.SetEndYear(endTime.DateTime().Year());
       
  1392 			}
       
  1393 
       
  1394 		// WKST (which defines the day on which a week starts) is not
       
  1395 		// supported by the agenda timezones.
       
  1396 		thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegUntil);
       
  1397 		if (thePos != KErrNotFound)
       
  1398 			{
       
  1399 			ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8, KICalWkSt);
       
  1400 			// On continue ignore the WKST.
       
  1401 			}
       
  1402 
       
  1403 		// BySecond, ByMinute, ByHour, ByYearDay, ByWeekNo are not
       
  1404 		// supported by the agenda timezones.
       
  1405 		thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegBySecond);
       
  1406 		if (thePos == KErrNotFound)
       
  1407 			{
       
  1408 			thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegByMinute);
       
  1409 			}
       
  1410 		if (thePos == KErrNotFound)
       
  1411 			{
       
  1412 			thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegByHour);
       
  1413 			}
       
  1414 		if (thePos == KErrNotFound)
       
  1415 			{
       
  1416 			thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegByYearDay);
       
  1417 			}
       
  1418 		if (thePos == KErrNotFound)
       
  1419 			{
       
  1420 			thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegByWeekNo);
       
  1421 			}
       
  1422 		if (thePos != KErrNotFound)
       
  1423 			{
       
  1424 			ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8, KICalRRule);
       
  1425 			// On continue ignore the unsupported field.
       
  1426 			}
       
  1427 
       
  1428 		// ByMonth
       
  1429 		TBool haveMonth = EFalse;
       
  1430 		thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegByMonth);
       
  1431 		if (thePos != KErrNotFound)
       
  1432 			{
       
  1433 			if (recRules[thePos]->Values().Count() > 0)
       
  1434 				{
       
  1435 				TMonth month = recRules[thePos]->Values()[0]->MonthL();
       
  1436 				haveMonth = ETrue;
       
  1437 				tzrule.iMonth = month;
       
  1438 				if (recRules[thePos]->Values().Count() > 1)
       
  1439 					{
       
  1440 					ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8, KICalByMonth);
       
  1441 					// On continue ignore the additional months.
       
  1442 					}
       
  1443 				}
       
  1444 			}
       
  1445 
       
  1446 		if (!haveMonth)
       
  1447 			{
       
  1448 			tzrule.iMonth = dateTime.Month();
       
  1449 			}
       
  1450 
       
  1451 		// ByDay
       
  1452 		TBool haveDay = EFalse;
       
  1453 		TInt daypos;
       
  1454 		thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegByDay);
       
  1455 		if (thePos != KErrNotFound)
       
  1456 			{
       
  1457 			if (recRules[thePos]->Values().Count() > 0)
       
  1458 				{
       
  1459 				TDay day;
       
  1460 				recRules[thePos]->Values()[0]->GetDayL(day, daypos);
       
  1461 				haveDay = ETrue;
       
  1462 				tzrule.iDayOfWeek = day;
       
  1463 				if (recRules[thePos]->Values().Count() > 1)
       
  1464 					{
       
  1465 					ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8, KICalByDay);
       
  1466 					// On continue ignore extra days.
       
  1467 					}
       
  1468 				}
       
  1469 			}
       
  1470 
       
  1471 		if (haveDay)
       
  1472 			{
       
  1473 			if (daypos == 0)
       
  1474 				{
       
  1475 				ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8, KICalByDay, EFalse);
       
  1476 				// We cannot handle this - on continue skip.
       
  1477 				}
       
  1478 			else if (daypos < 0)
       
  1479 				{
       
  1480 				// We cant handle -2,-3 etc, so we assume -1
       
  1481 				tzrule.iDayRule = ETzDayInLastWeekOfMonth;
       
  1482 				tzrule.iDayOfMonth = 0;
       
  1483 				}
       
  1484 			else
       
  1485 				{
       
  1486 				if (daypos > KMaxWeekDayNum)
       
  1487 					{
       
  1488 					ReportErrorL(MAgnImportObserver::EImpErrorInvalidData, KNullDesC8, KICalByDay);
       
  1489 					// On continue, assume the KMaxWeekDayNum.
       
  1490 					daypos = KMaxWeekDayNum;
       
  1491 					}
       
  1492 				tzrule.iDayRule = ETzDayAfterDate;
       
  1493 				tzrule.iDayOfMonth = (daypos - 1) * KDaysPerWeek;
       
  1494 				}
       
  1495 			}
       
  1496 		else
       
  1497 			{
       
  1498 			tzrule.iDayRule = ETzFixedDate;
       
  1499 			tzrule.iDayOfMonth = dateTime.Day();
       
  1500 			}
       
  1501 
       
  1502 		// ByMonthDay and BySetPos can in theory be supported under
       
  1503 		// some circumstances, but right now they aren't.
       
  1504 		thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegByMonthDay);
       
  1505 		if (thePos == KErrNotFound)
       
  1506 			{
       
  1507 			thePos = FindRuleSegment(recRules, CICalRuleSegment::ESegByPos);
       
  1508 			}
       
  1509 		if (thePos != KErrNotFound)
       
  1510 			{
       
  1511 			ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8, KICalRRule);
       
  1512 			// On continue ignore both fields.
       
  1513 			}
       
  1514 
       
  1515 		tzrule.iTimeOfChange = dateTime.Hour() * KMinutesInOneHour + dateTime.Minute();
       
  1516 		tzrule.iTo = TCalTime::MaxTime();
       
  1517 		aRules.AddRuleL(tzrule);
       
  1518 		}
       
  1519 	else // no rrule
       
  1520 		{
       
  1521 		tzrule.iDayRule = ETzFixedDate;
       
  1522 		tzrule.iMonth = dateTime.Month();
       
  1523 		tzrule.iDayOfMonth = dateTime.Day();
       
  1524 		tzrule.iTimeOfChange = dateTime.Hour() * KMinutesInOneHour + dateTime.Minute();
       
  1525 		aRules.AddRuleL(tzrule);
       
  1526 		}
       
  1527 	CleanupStack::PopAndDestroy(&recRules);
       
  1528 	
       
  1529 	TRACE_EXIT_POINT;
       
  1530 	}
       
  1531 
       
  1532 /**
       
  1533 *     IMPORT PROPERTY FUNCTIONS
       
  1534 *     =========================
       
  1535 */
       
  1536 
       
  1537 /**
       
  1538 Helper function for translating categories from the pure text format of
       
  1539 iCalendar to the enumerated type of Agenda.
       
  1540 @param aProperty A category property.
       
  1541 @param aEntry An entry into which to put the categories.
       
  1542 @internalTechnology
       
  1543 */
       
  1544 void CAgnVersit2Importer::ImportCategoriesL( const CICalProperty& aProperty,
       
  1545                                              CCalEntry& aEntry ) const
       
  1546 	{
       
  1547 	TRACE_ENTRY_POINT;
       
  1548 	
       
  1549 	TInt valCount = aProperty.Values().Count();
       
  1550 	for (TInt pnum = 0; pnum < valCount; ++pnum)
       
  1551 		{
       
  1552 		TPtrC name(aProperty.Values()[pnum]->TextL());
       
  1553 		CCalCategory* cat = NULL;
       
  1554 		if (name.CompareF(iStringProvider.StringL(EICalAppointment)) == 0)
       
  1555 			{
       
  1556 			cat = CCalCategory::NewL(CCalCategory::ECalAppointment);
       
  1557 			}
       
  1558 		else if (name.CompareF(iStringProvider.StringL(EICalBusiness)) == 0)
       
  1559 			{
       
  1560 			cat = CCalCategory::NewL(CCalCategory::ECalBusiness);
       
  1561 			}
       
  1562 		else if (name.CompareF(iStringProvider.StringL(EICalEducation)) == 0)
       
  1563 			{
       
  1564 			cat = CCalCategory::NewL(CCalCategory::ECalEducation);
       
  1565 			}
       
  1566 		else if (name.CompareF(iStringProvider.StringL(EICalHoliday)) == 0)
       
  1567 			{
       
  1568 			cat = CCalCategory::NewL(CCalCategory::ECalHoliday);
       
  1569 			}
       
  1570 		else if (name.CompareF(iStringProvider.StringL(EICalMeeting)) == 0)
       
  1571 			{
       
  1572 			cat = CCalCategory::NewL(CCalCategory::ECalMeeting);
       
  1573 			}
       
  1574 		else if (name.CompareF(iStringProvider.StringL(EICalMisc)) == 0)
       
  1575 			{
       
  1576 			cat = CCalCategory::NewL(CCalCategory::ECalMiscellaneous);
       
  1577 			}
       
  1578 		else if (name.CompareF(iStringProvider.StringL(EICalPersonal)) == 0)
       
  1579 			{
       
  1580 			cat = CCalCategory::NewL(CCalCategory::ECalPersonal);
       
  1581 			}
       
  1582 		else if (name.CompareF(iStringProvider.StringL(EICalPhoneCall)) == 0)
       
  1583 			{
       
  1584 			cat = CCalCategory::NewL(CCalCategory::ECalPhoneCall);
       
  1585 			}
       
  1586 		else if (name.CompareF(iStringProvider.StringL(EICalSick)) == 0)
       
  1587 			{
       
  1588 			cat = CCalCategory::NewL(CCalCategory::ECalSickDay);
       
  1589 			}
       
  1590 		else if (name.CompareF(iStringProvider.StringL(EICalSpecial)) == 0)
       
  1591 			{
       
  1592 			cat = CCalCategory::NewL(CCalCategory::ECalSpecialOccasion);
       
  1593 			}
       
  1594 		else if (name.CompareF(iStringProvider.StringL(EICalTravel)) == 0)
       
  1595 			{
       
  1596 			cat = CCalCategory::NewL(CCalCategory::ECalTravel);
       
  1597 			}
       
  1598 		else if (name.CompareF(iStringProvider.StringL(EICalVacation)) == 0)
       
  1599 			{
       
  1600 			cat = CCalCategory::NewL(CCalCategory::ECalVacation);
       
  1601 			}
       
  1602 		else
       
  1603 			{
       
  1604 			cat = CCalCategory::NewL(name);
       
  1605 			}
       
  1606 		aEntry.AddCategoryL(cat);
       
  1607 		}
       
  1608 	TRACE_EXIT_POINT;
       
  1609 	}
       
  1610 
       
  1611 /**
       
  1612 A function to import a CLASS property into a format suitable for Agenda.
       
  1613 @param aProperty The CLASS property to translate.
       
  1614 @param aEntry The entry to add the rules to.
       
  1615 @internalTechnology
       
  1616 */
       
  1617 void CAgnVersit2Importer::ImportClassL(const CICalProperty& aProperty, CCalEntry& aEntry)
       
  1618 	{
       
  1619 	TRACE_ENTRY_POINT;
       
  1620 	
       
  1621 	if (aProperty.Values().Count() > 0)
       
  1622 		{
       
  1623 		// Ignore any values after the first one
       
  1624 		TPtrC name(aProperty.Values()[0]->TextL());
       
  1625 		if (name.CompareF(KICalPublic) == 0)
       
  1626 			{
       
  1627 			aEntry.SetReplicationStatusL(CCalEntry::EOpen);
       
  1628 			}
       
  1629 		else if (name.CompareF(KICalPrivate) == 0)
       
  1630 			{
       
  1631 			aEntry.SetReplicationStatusL(CCalEntry::EPrivate);
       
  1632 			}
       
  1633 		else if (name.CompareF(KICalConfidential) == 0)
       
  1634 			{
       
  1635 			aEntry.SetReplicationStatusL(CCalEntry::ERestricted);
       
  1636 			}
       
  1637 		else
       
  1638 			{
       
  1639 			ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, aEntry.UidL(), name);
       
  1640 			// On continue ignore the class.
       
  1641 			}
       
  1642 		}
       
  1643 	else
       
  1644 		{
       
  1645 		ReportErrorL(MAgnImportObserver::EImpErrorMissingData, aEntry.UidL(), KICalRRule);
       
  1646 		// On continue ignore the class.
       
  1647 		}
       
  1648 	TRACE_EXIT_POINT;
       
  1649 	}
       
  1650 
       
  1651 /**
       
  1652 A function to translate an RRULE property into a TCalRRule for Agenda.
       
  1653 @param aProperty The RRULE property to translate.
       
  1654 @param aEntry The entry to add the rules to.
       
  1655 @param aStartTime The DTSTART of the parent component.
       
  1656 @return ETrue if the rule is imported, else EFalse.
       
  1657 @internalTechnology
       
  1658 */
       
  1659 TBool CAgnVersit2Importer::ImportRRuleL( const CICalProperty& aProperty,
       
  1660                                          CCalEntry& aEntry,
       
  1661                                          const TCalTime& aStartTime )
       
  1662 	{
       
  1663 	TRACE_ENTRY_POINT;
       
  1664 
       
  1665     //Create a new recurrence rule importer
       
  1666     CAgnRRuleImporter *importer = CAgnRRuleImporter::NewLC( *this );
       
  1667 
       
  1668     //import the recurrence rule 
       
  1669     TBool importRRule = importer->ImportL( aProperty, aEntry, aStartTime );
       
  1670     
       
  1671     if( importRRule )
       
  1672         {
       
  1673         iNeedsTzRules = ETrue; 
       
  1674         }
       
  1675     
       
  1676     CleanupStack::PopAndDestroy( importer );
       
  1677     
       
  1678     TRACE_EXIT_POINT;
       
  1679     
       
  1680     //return true if the rule is imported
       
  1681     return importRRule;
       
  1682 	}
       
  1683 
       
  1684 
       
  1685 
       
  1686 //
       
  1687 //     HELPER FUNCTIONS
       
  1688 //     ================
       
  1689 //
       
  1690 
       
  1691 
       
  1692 /**
       
  1693 Takes a property, a TCalTime, and an index into the set of values of the
       
  1694 property, and populates the TCalTime from the value, performing any required
       
  1695 timezone conversions first.
       
  1696 @param aProperty A property which has a date or date-time type.
       
  1697 @param aTime The time to put the resulting UTC time into.
       
  1698 @param aDefaultType Enumeration of the type of value being passed.
       
  1699 @param aValue The index of the property value to use, for properties which have
       
  1700 more than one.
       
  1701 @internalTechnology
       
  1702 */
       
  1703 void CAgnVersit2Importer::GetCalTimeL( const CICalProperty& aProperty,
       
  1704                                        TCalTime& aTime,
       
  1705                                        TValueType aValueType,
       
  1706                                        TInt aValue )
       
  1707 	{
       
  1708 	TRACE_ENTRY_POINT;
       
  1709 	
       
  1710 	// Find the property value, value parameter and tzid parameter:
       
  1711 	if (aProperty.Values().Count() < aValue)
       
  1712 		{
       
  1713 		ReportErrorL(MAgnImportObserver::EImpErrorMissingData, KNullDesC8, aProperty.Type(), EFalse);
       
  1714 		// We cannot continue - we interpret continue as skip.
       
  1715 		}
       
  1716 
       
  1717 	const CICalPropertyParam* valuetype = aProperty.FindParam(KICalValue);
       
  1718 	if (valuetype)
       
  1719 		{
       
  1720 		if (valuetype->Values().Count() < 1)
       
  1721 			{
       
  1722 			ReportErrorL(MAgnImportObserver::EImpErrorMissingData, KNullDesC8, KICalValue);
       
  1723 			// On continue, use the default type passed in the function arguments.
       
  1724 			}
       
  1725 		else
       
  1726 			{
       
  1727 			TPtrC vt(valuetype->Values()[0]->TextL());
       
  1728 			if (vt.CompareF(KICalDate) == 0)
       
  1729 				{
       
  1730 				aValueType = EDate;
       
  1731 				}
       
  1732 			else if (vt.CompareF(KICalDateTime) == 0)
       
  1733 				{
       
  1734 				aValueType = EDateTime;
       
  1735 				}
       
  1736 			else
       
  1737 				{
       
  1738 				ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8, vt, EFalse);
       
  1739 				// We can't continue - skip instead.
       
  1740 				}
       
  1741 			}
       
  1742 		}
       
  1743 
       
  1744 	TTime dateAndTime;
       
  1745 	CICalValue::TTimeZoneType tzType = CICalValue::EUtcTime;
       
  1746 
       
  1747 	CICalValue* value = aProperty.Values()[aValue];
       
  1748 
       
  1749 	switch (aValueType)
       
  1750 		{
       
  1751 		case EDate :
       
  1752 			value->GetDateL(dateAndTime);
       
  1753 			break;
       
  1754 		case EDateTime :
       
  1755 			value->GetDateTimeL(dateAndTime, tzType);
       
  1756 			break;
       
  1757 		case ETime :
       
  1758 			value->GetTimeL(dateAndTime, tzType);
       
  1759 			break;
       
  1760 		case EDefault :		// fall through..
       
  1761 		case EDuration :	// not supported, fall through
       
  1762 		case EPeriod :		// not supported, fall through
       
  1763 		default :
       
  1764 			{
       
  1765 			ReportErrorL(MAgnImportObserver::EImpErrorNotSupported, KNullDesC8, KICalPeriod, EFalse);
       
  1766 			// We can't continue - skip instead.
       
  1767 			break;
       
  1768 			}
       
  1769 		}
       
  1770 
       
  1771 	const CICalPropertyParam* tzid = aProperty.FindParam(KICalTzid);
       
  1772 
       
  1773 	// Handle timezone information:
       
  1774 	if (tzType == CICalValue::EUtcTime)
       
  1775 		{
       
  1776 		// A trailing Z means UTC:
       
  1777 		aTime.SetTimeUtcL(dateAndTime);
       
  1778 		}
       
  1779 	else if (!tzid || tzid->Values().Count() < 1)
       
  1780 		{
       
  1781 		// No trailing Z and no timezone ID.
       
  1782 		// This is a floating time.
       
  1783 		aTime.SetTimeLocalFloatingL(dateAndTime);
       
  1784 		}
       
  1785 	else
       
  1786 		{
       
  1787 		// Find the name of the timezone, and the timezone with that name:
       
  1788 		const CTzRules* rules = FindTzRule(tzid->Values()[0]->TextL());
       
  1789 
       
  1790 		if (!rules)
       
  1791 			{
       
  1792 			ReportErrorL(MAgnImportObserver::EImpErrorMissingData,KNullDesC8, aProperty.Type());
       
  1793 			// On continue, assume UTC.
       
  1794 			}
       
  1795 		else
       
  1796 			{
       
  1797 			// Remember the timezone:
       
  1798 			iCurrentTzRules = rules;
       
  1799 			// All times are stored in Agenda in UTC, and the timezone
       
  1800 			// applied by Agenda where appropriate:
       
  1801 			rules->ConvertToUtcL(dateAndTime);
       
  1802 			}
       
  1803 
       
  1804 		// Set the time:
       
  1805 		aTime.SetTimeUtcL(dateAndTime);
       
  1806 		}
       
  1807 	TRACE_EXIT_POINT;
       
  1808 	}
       
  1809 
       
  1810 /**
       
  1811 Searches through a set of rule segments and finds the segment corresponding to
       
  1812 a particular type.
       
  1813 @param aRules The array of rules to search.
       
  1814 @param aType The type of segment to search for from CICalRuleSegment::TSegmentType.
       
  1815 @see CICalRuleSegment::TSegmentType
       
  1816 @return The index of the rule within the array, or KErrNotFound
       
  1817 @internalTechnology
       
  1818 */
       
  1819 TInt CAgnVersit2Importer::FindRuleSegment( const RPointerArray<CICalRuleSegment>& aRules,
       
  1820                                            CICalRuleSegment::TSegmentType aType ) const
       
  1821 	{
       
  1822 	TRACE_ENTRY_POINT;
       
  1823 	
       
  1824 	for (TInt r = aRules.Count() - 1; r > -1; --r)
       
  1825 		{
       
  1826 		if (aRules[r]->Type() == aType)
       
  1827 			{
       
  1828 			TRACE_EXIT_POINT;
       
  1829 			return r;
       
  1830 			}
       
  1831 		}
       
  1832 	TRACE_EXIT_POINT;
       
  1833 	return KErrNotFound;
       
  1834 	}
       
  1835 
       
  1836 /**
       
  1837 Searches through the internally stored array of time zone rules looking for one
       
  1838 with a particular name, and returns its address. This does not transfer
       
  1839 ownership of the rule.
       
  1840 @param aName The name of the timezone rule to find (corresponding to TZID)
       
  1841 @return A pointer to the rule, or zero if no matching rule is found.
       
  1842 @internalTechnology
       
  1843 */
       
  1844 const CTzRules* CAgnVersit2Importer::FindTzRule(const TDesC& aName) const
       
  1845 	{
       
  1846 	TRACE_ENTRY_POINT;
       
  1847 	
       
  1848 	TInt tzCount = iTzRules.Count();
       
  1849 	for (TInt r = 0; r < tzCount; ++r)
       
  1850 		{
       
  1851 		if (iTzRules[r]->iName->CompareF(aName) == 0)
       
  1852 			{
       
  1853 			TRACE_EXIT_POINT;
       
  1854 			return iTzRules[r]->iRules;
       
  1855 			}
       
  1856 		}
       
  1857 	
       
  1858 	TRACE_EXIT_POINT;
       
  1859 	return NULL;
       
  1860 	}
       
  1861 
       
  1862 /**
       
  1863 Reports an error through the MAgnImportObserver interface, and then leaves if
       
  1864 the return value is anything other than
       
  1865 MAgnImportObserver::EImpResponseContinue. The return value is stored in
       
  1866 iResponse.
       
  1867 @param aType The type of error which occurred
       
  1868 @param aUid The Uid of the entry in which it occurred, if known, or KNullDesC
       
  1869 if not.
       
  1870 @param aContext A textual indication of where the error occurred.
       
  1871 @param aCanContinue If this is not ETrue (default = ETrue) then a response of
       
  1872 EImpResponseContinue will be handled as an EImpResponseSkip
       
  1873 @leave KErrAbort
       
  1874 @internalTechnology
       
  1875 */
       
  1876 void CAgnVersit2Importer::ReportErrorL( MAgnImportObserver::TImpError aType,
       
  1877                                         const TDesC8& aUid,
       
  1878                                         const TDesC& aContext,
       
  1879                                         TBool aCanContinue )
       
  1880 	{
       
  1881 	TRACE_ENTRY_POINT;
       
  1882 	
       
  1883 	iResponse = iImportObserver->AgnImportErrorL(aType, aUid, aContext);
       
  1884 	if (iResponse != MAgnImportObserver::EImpResponseContinue)
       
  1885 		{
       
  1886 		TRACE_EXIT_POINT;
       
  1887 		User::Leave(KErrAbort);
       
  1888 		}
       
  1889 	else if (!aCanContinue)
       
  1890 		{
       
  1891 		iResponse = MAgnImportObserver::EImpResponseSkip;
       
  1892 		
       
  1893 		TRACE_EXIT_POINT;
       
  1894 		User::Leave(KErrAbort);
       
  1895 		}
       
  1896     
       
  1897     TRACE_EXIT_POINT;
       
  1898 	}
       
  1899 
       
  1900 // End of file.