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