meetingrequest/mragnversit2/src/cesmragnversit2importer.cpp
changeset 0 8466d47a6819
equal deleted inserted replaced
-1:000000000000 0:8466d47a6819
       
     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