/*
* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Converts event properties PIM API <-> versit
 *
*/


// CLASS HEADER
#include "cpimeventpropertyconverter.h"

// INTERNAL INCLUDES
#include "pimcommon.h" // tpimfield
#include "pimpanics.h"
#include "pimversit.h"
#include "cpimparserproperty.h"
#include "cpimitem.h"
#include "cpimeventitem.h"
#include "mpimrepeatruledata.h"
#include "cleanupresetanddestroy.h"
#include "logger.h"

// EXTERNAL INCLUDES
#include <vcal.h>

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CPIMEventPropertyConverter* CPIMEventPropertyConverter::NewL()
{
    JELOG2(EPim);
    CPIMEventPropertyConverter* self =
        new(ELeave) CPIMEventPropertyConverter();
    return self;
}

// Destructor
CPIMEventPropertyConverter::~CPIMEventPropertyConverter()
{
    JELOG2(EPim);
}

// -----------------------------------------------------------------------------
// CPIMCardConverter::ConvertPropertyL
// Inserts a proprety from a vEvent to a PIM Event Item as a field
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertPropertyL(
    const CParserProperty& aProperty, // property to convert
    CPIMEventItem& aItem, // item to insert the field to
    TPIMDate& aAlarm) // DALARM is stored here
{
    JELOG2(EPim);
    TUid valueTypeUid = aProperty.Uid();
    TInt valueType = valueTypeUid.iUid;

    // The following, rather ugly, cast makes it possible for us to access
    // the protected iArrayOfParams field.
    const CPIMParserProperty& property =
        static_cast<const CPIMParserProperty&>(aProperty);

    if (aProperty.Name().CompareF(KVersitTokenCLASS) == 0)
    {
        ConvertClassPropertyL(property, aItem);
    }
    else
    {
        switch (valueType)
        {
        case KVersitPropertyDateTimeUid:
        {
            // Start, End, DALARM
            ConvertDatePropertyL(property, aItem);
            break;
        }
        case KVersitPropertyHBufCUid:
        {
            // summary, location
            ConvertStringPropertyL(property, aItem);
            break;
        }
        case KVersitPropertyMultiDateTimeUid:
        {
            // exdate
            ConvertExDatePropertyL(property, aItem);
            break;
        }
        case KVCalPropertyRecurrenceUid:
        {
            // repeat rule
            ConvertRepeatRulePropertyL(property, aItem);
            break;
        }
        case KVCalPropertyAlarmUid:
        {
            // DALARM
            ConvertAlarmPropertyL(property, aAlarm);
            break;
        }
        default:
        {
            // don't support, don't care
        }
        }
    }
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertEventFieldL
// Inserts a Field from a PIM Event Item to CParserVCard as a property.
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertEventFieldL(const CPIMItem& aItem, // item to read the field from
        CParserVCalEntity& aParser, // parser to insert the property to.
        TPIMEventField aField) // field to convert
{
    JELOG2(EPim);
    TInt valueCount = aItem.CountValuesL(aField);
    for (TInt i = 0; i < valueCount; i++)
    {
        switch (aField)
        {
        case EPIMEventAlarm:
        {
            ConvertAlarmFieldL(aItem, aParser, aField, i);
            break;
        }
        case EPIMEventStart:
        case EPIMEventEnd:
        case EPIMEventRevision:
        {
            ConvertDateFieldL(aItem, aParser, aField, i);
            break;
        }
        case EPIMEventSummary:
        case EPIMEventLocation:
        case EPIMEventNote:
            // UID is required by VFX. Do not fix even though this is wrong
        case EPIMEventUid:
        {
            ConvertStringFieldL(aItem, aParser, aField, i);
            break;
        }
        case EPIMEventClass:
        {
            ConvertClassFieldL(aItem, aParser, aField, i);
            break;
        }
        default:
        {
            __ASSERT_DEBUG(EFalse, User::Panic(KPIMPanicCategory,
                                               EPIMPanicUnsupportedField));
            return;
        }
        }
    }
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertRepeatRuleL
// Inserts a repeat rule to a parser.
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertRepeatRuleL(
    const MPIMRepeatRuleData* aRepeat, CParserVCalEntity& aParser)
{
    JELOG2(EPim);
    // First exception dates
    const CArrayFix<TPIMDate>& exceptionDates = aRepeat->GetExceptDatesL();
    ConvertExceptionDatesL(exceptionDates, aParser);

    // The interval is always set to 1 - only exception is every 2 weeks repeat
    TInt interval = 1;
    TInt frequency = 0;
    TVersitDateTime* versitEndDate = NULL;

    GetRepeatRuleFieldsL(aRepeat, &interval, &frequency, &versitEndDate);
    if (versitEndDate)
    {
        CleanupDeletePushL(versitEndDate);
    }

    CVersitRecurrence* recurrence = CreateRecurrenceL(frequency, interval,
                                    versitEndDate);

    if (versitEndDate)
    {
        CleanupStack::Pop(versitEndDate); // versitEndDate is owned by recurrence now
    }
    CleanupStack::PushL(recurrence);

    CParserPropertyValue* propertyValue =
        new(ELeave) CParserPropertyValueRecurrence(recurrence);
    // recurrence is now owned by propertyValue
    CleanupStack::Pop(recurrence);
    AddPropertyToParserL(propertyValue, KVersitTokenRRULE(), aParser);
    // Needed cleanup stack items are popped out in the AddPropretyToParserL
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::CPIMEventPropertyConverter
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CPIMEventPropertyConverter::CPIMEventPropertyConverter()
{
    JELOG2(EPim);
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertDatePropertyL
// Converts a date field from a vCard to a PIM Event Item
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertDatePropertyL(
    const CPIMParserProperty& aProperty, // property to convert
    CPIMEventItem& aItem)
{
    JELOG2(EPim);
    TPIMField field = aProperty.MatchEventField();
    // Do not match unrecognized fields
    if (field == -1)
    {
        return;
    }

    CParserPropertyValueDate* propertyValue =
        static_cast<CParserPropertyValueDate*>(aProperty.Value());
    const TVersitDateTime* value = propertyValue->Value();

    TPIMDate date(value->iDateTime);
    aItem.AddDateL(field, KPIMAttrNone, date);
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertAlarmPropertyL
// Converts an alarm field from a vCard to a PIM Event Item
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertAlarmPropertyL(
    const CPIMParserProperty& aProperty, // property to convert
    TPIMDate& aAlarm) // item to insert the field to
{
    JELOG2(EPim);
    if (aProperty.MatchEventField() != EPIMEventAlarm)
    {
        return;
    }

    CParserPropertyValueAlarm* propertyValue =
        static_cast<CParserPropertyValueAlarm*>(aProperty.Value());
    const CVersitAlarm* value = propertyValue->Value();

    const TVersitDateTime* versitDT = value->iRunTime;
    TPIMDate date(versitDT->iDateTime);

    aAlarm = date;
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertStringPropertyL
// Converts a string property from a vCalendar to a PIM Event Item
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertStringPropertyL(
    const CPIMParserProperty& aProperty, // property to convert
    CPIMEventItem& aItem) // item to insert the field to
{
    JELOG2(EPim);
    TPIMField field = aProperty.MatchEventField();
    // Do not convert unrecognized fields
    if (field == -1)
    {
        return;
    }

    CParserPropertyValueHBufC* propertyValue =
        static_cast<CParserPropertyValueHBufC*>(aProperty.Value());
    HBufC* value = propertyValue->TakeValueOwnership();
    CleanupStack::PushL(value);
    aItem.AddStringL(field, KPIMAttrNone, value);
    CleanupStack::Pop(value); // owned by aItem
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertRepeatRulePropertyL
// Inserts RRULE proprety from a vEvent to a PIM Event Item as a repeat rule
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertRepeatRulePropertyL(
    const CPIMParserProperty& aProperty, // property to convert
    CPIMEventItem& aItem) // item to insert the field to
{
    JELOG2(EPim);
    if (aProperty.Name().CompareF(KVersitTokenRRULE) != 0)
    {
        // Some unsupported recurrence data (i.e. EXRULE)
        return;
    }
    MPIMRepeatRuleData* repeatRule = aItem.GetRepeat();

    CParserPropertyValueRecurrence* propertyValue =
        static_cast<CParserPropertyValueRecurrence*>(aProperty.Value());
    CVersitRecurrence* value = propertyValue->Value();
    switch (value->iRepeatType)
    {
    case CVersitRecurrence::EDaily:
    {
        repeatRule->SetIntL(EPIMRepeatRuleFrequency, EPIMRepeatRuleDaily);
        break;
    }
    case CVersitRecurrence::EWeekly:
    {
        repeatRule->SetIntL(EPIMRepeatRuleFrequency, EPIMRepeatRuleWeekly);
        repeatRule->SetIntL(EPIMRepeatRuleInterval, value->iInterval);
        break;
    }
    case CVersitRecurrence::EMonthlyByPos:
    case CVersitRecurrence::EMonthlyByDay:
    {
        repeatRule->SetIntL(EPIMRepeatRuleFrequency, EPIMRepeatRuleMonthly);
        break;
    }
    case CVersitRecurrence::EYearlyByMonth:
    case CVersitRecurrence::EYearlyByDay:
    {
        repeatRule->SetIntL(EPIMRepeatRuleFrequency, EPIMRepeatRuleYearly);
        break;
    }
    default:
    {
        // unknown frequency
        return;
    }
    }

    TVersitDateTime* versitEndDate = value->iEndDate;
    if (versitEndDate)
    {
        TPIMDate endDate(versitEndDate->iDateTime);
        repeatRule->SetDateL(EPIMRepeatRuleEnd, endDate);
    }

    aItem.SetRepeating(ETrue);
}
// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertExDatePropertyL
// Inserts EXDATE proprety from a vEvent to a PIM Event Item as a repeat rule
// field
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertExDatePropertyL(
    const CPIMParserProperty& aProperty, // property to convert
    CPIMEventItem& aItem) // item to insert the field to
{
    JELOG2(EPim);
    if (aProperty.Name().CompareF(KVersitTokenEXDATE) != 0)
    {
        // some unsupported multidate
        return;
    }
    MPIMRepeatRuleData* repeatRule = aItem.GetRepeat();

    CParserPropertyValueMultiDateTime* propertyValue =
        static_cast<CParserPropertyValueMultiDateTime*>(aProperty.Value());
    CArrayPtr<TVersitDateTime>* value = propertyValue->Value();
    TInt valueCount = value->Count();
    for (TInt i = 0; i < valueCount; i++)
    {
        TPIMDate date(value->At(i)->iDateTime);
        repeatRule->AddExceptDateL(date);
    }
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertClassPropertyL
// Converts CLASS property to a PIM Event item.
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertClassPropertyL(
    const CPIMParserProperty& aProperty, CPIMEventItem& aItem)
{
    JELOG2(EPim);
    CParserPropertyValueHBufC* propertyValue =
        static_cast<CParserPropertyValueHBufC*>(aProperty.Value());

    const TPtrC classStringPtr = propertyValue->Value();
    TInt classInt = KErrCorrupt;

    if (classStringPtr.CompareF(KPIMClassStringPublic) == 0)
    {
        classInt = EPIMEventClassPublic;
    }
    else if (classStringPtr.CompareF(KPIMClassStringPrivate) == 0)
    {
        classInt = EPIMEventClassPrivate;
    }
    else if (classStringPtr.CompareF(KPIMClassStringConfidential) == 0)
    {
        classInt = EPIMEventClassConfidential;
    }
    // else the class value in the originating vCalendar is flawed - ignore

    if (classInt != KErrCorrupt)
    {
        aItem.addInt(EPIMEventClass, KPIMAttrNone, classInt);
    }
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertExceptionDatesL
// Inserts exceptiondates to a parser.
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertExceptionDatesL(const CArrayFix<
        TPIMDate>& aDates, CParserVCalEntity& aParser)
{
    JELOG2(EPim);
    TInt exDateCount = aDates.Count();
    if (exDateCount > 0)
    {
        CArrayPtrFlat<TVersitDateTime>* versitExDates =
            new(ELeave) CArrayPtrFlat<TVersitDateTime> (exDateCount);
        CleanupStack::PushL(versitExDates);
        CleanupResetAndDestroyPushL(*versitExDates);
        for (TInt i = 0; i < exDateCount; i++)
        {
            TVersitDateTime
            * versitDateTime =
                new(ELeave) TVersitDateTime(aDates.At(i).DateTime(), TVersitDateTime::EIsUTC);
            CleanupDeletePushL(versitDateTime);
            versitExDates->AppendL(versitDateTime);
            CleanupStack::Pop(versitDateTime); // versitDateTime
        }
        CParserPropertyValue* propertyValue =
            new(ELeave) CParserPropertyValueMultiDateTime(versitExDates);
        CleanupStack::Pop(2); // versitExDates is now owned by propertyValue
        AddPropertyToParserL(propertyValue, KVersitTokenEXDATE(), aParser);
        // Needed cleanup stack items are popped out in the AddPropretyToParserL
    }
}
// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertDateFieldL
// Converts a date field from a PIM Event Item to a CParserVCard.
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertDateFieldL(const CPIMItem& aItem, // item to convert from
        CParserVCalEntity& aParser, // parser to insert the property to.
        TPIMEventField aField, // field to convert
        TInt aIndex) // index to the field
{
    JELOG2(EPim);
    const TPIMDate date = aItem.GetDateL(aField, aIndex);
    TDateTime dateTime = date.DateTime();
    TVersitDateTime* versitDateTime =
        new(ELeave) TVersitDateTime(dateTime, TVersitDateTime::EIsUTC);
    CleanupDeletePushL(versitDateTime);

    CParserPropertyValue* propertyValue =
        new(ELeave) CParserPropertyValueDateTime(versitDateTime);
    // versitDateTime is now owned by propertyValue
    CleanupStack::Pop(versitDateTime);

    switch (aField)
    {
    case EPIMEventStart:
    {
        AddPropertyToParserL(propertyValue, KVersitTokenDTSTART(), aParser);
        // Needed cleanup stack items are popped
        // out in the AddPropretyToParserL
        break;
    }
    case EPIMEventEnd:
    {
        AddPropertyToParserL(propertyValue, KVersitTokenDTEND(), aParser);
        // Needed cleanup stack items are popped
        // out in the AddPropretyToParserL
        break;
    }
    case EPIMEventRevision:
    {
        AddPropertyToParserL(propertyValue, KVersitTokenLASTMODIFIED(), aParser);
        // Needed cleanup stack items are popped
        // out in the AddPropretyToParserL
        break;
    }
    default:
    {
        __ASSERT_DEBUG(EFalse, User::Panic(KPIMPanicCategory,
                                           EPIMPanicUnsupportedDateField));
    }
    }
}
// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertAlarmFieldL
// Converts an alarm field from a PIM Event Item to a CParserVCard.
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertAlarmFieldL(const CPIMItem& aItem, // item to convert from
        CParserVCalEntity& aParser, // parser to insert the property to.
        TPIMEventField aField, // field to convert
        TInt aIndex) // index to the field
{
    JELOG2(EPim);
    const TInt KAlarmInterval = aItem.getInt(aField, aIndex);
    const TTimeIntervalSeconds KTimeInterval(KAlarmInterval);

    // Check that there exists start date. If item is not written to
    // database there might not be start date present
    if (aItem.CountValuesL(EPIMEventStart) == 0)
    {
        return;
    }

    // Start date present, so conversion can be made
    const TPIMDate KStartDate = aItem.GetDateL(EPIMEventStart, 0);
    TTime alarmTime(KStartDate);
    alarmTime -= KTimeInterval;
    TDateTime dateTime = alarmTime.DateTime();
    TVersitDateTime* versitDateTime =
        new(ELeave) TVersitDateTime(dateTime, TVersitDateTime::EIsUTC);
    CleanupDeletePushL(versitDateTime);

    CVersitAlarm* versitAlarm = CVersitAlarm::NewL(versitDateTime, NULL, 0,
                                KNullDesC, KNullDesC);
    // versitDateTime is now owned by versitAlarm
    CleanupStack::Pop(versitDateTime);
    CleanupStack::PushL(versitAlarm);
    CParserPropertyValue* propertyValue =
        new(ELeave) CParserPropertyValueAlarm(versitAlarm);
    // versitAlarm is now owned by propertyValue
    CleanupStack::Pop(versitAlarm);
    AddPropertyToParserL(propertyValue, KVersitTokenDALARM(), aParser);
    // Needed cleanup stack items are popped out in the AddPropretyToParserL
}
// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertStringFieldL
// Converts a string field from a PIM Event Item to vCard
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertStringFieldL(const CPIMItem& aItem, // item to convert from
        CParserVCalEntity& aParser, // parser to write to
        TPIMEventField aField, // field to convert
        TInt aIndex) // index to the field
{
    JELOG2(EPim);
    const TDesC& string = aItem.GetStringL(aField, aIndex);
    CParserPropertyValue* propertyValue = CParserPropertyValueHBufC::NewL(
                                              string);

    switch (aField)
    {
    case EPIMEventSummary:
    {
        AddPropertyToParserL(propertyValue, KVersitTokenSUMMARY(), aParser);
        // Needed cleanup stack items are popped
        // out in the AddPropretyToParserL
        break;
    }
    case EPIMEventLocation:
    {
        AddPropertyToParserL(propertyValue, KVersitTokenLOCATION(), aParser);
        // Needed cleanup stack items are popped
        // out in the AddPropretyToParserL
        break;
    }
    case EPIMEventNote:
    {
        AddPropertyToParserL(propertyValue, KVersitTokenDESCRIPTION(), aParser);
        // Needed cleanup stack items are popped
        // out in the AddPropretyToParserL
        break;
    }
    case EPIMEventUid:
    {
        AddPropertyToParserL(propertyValue, KVersitTokenUID(), aParser);
        // Needed cleanup stack items are popped
        // out in the AddPropretyToParserL
        break;
    }
    default:
    {
        __ASSERT_DEBUG(EFalse, User::Panic(KPIMPanicCategory,
                                           EPIMPanicUnsupportedStringField));
    }
    }
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::ConvertClassFieldL
// Converts Event.CLASS field to a vCalendar.
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::ConvertClassFieldL(const CPIMItem& aItem,
        CParserVCalEntity& aParser, TPIMEventField aField, TInt aIndex)
{
    JELOG2(EPim);
    const TInt classVal = aItem.getInt(aField, aIndex);
    TPtrC classString(KPIMClassStringConfidential);

    switch (classVal)
    {
    case EPIMEventClassConfidential:
    {
        classString.Set(KPIMClassStringConfidential);
        break;
    }
    case EPIMEventClassPrivate:
    {
        classString.Set(KPIMClassStringPrivate);
        break;
    }
    case EPIMEventClassPublic:
    {
        classString.Set(KPIMClassStringPublic);
        break;
    }
    default:
    {
        __ASSERT_DEBUG(EFalse, User::Invariant());
        break;
    }
    }

    CParserPropertyValue* propertyValue = CParserPropertyValueHBufC::NewL(
                                              classString);
    AddPropertyToParserL(propertyValue, KVersitTokenCLASS(), aParser);
    // Needed cleanup stack items are popped out in the AddPropretyToParserL
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::GetRepeatRuleFieldsL
// Gets the fields from a repeat rule
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::GetRepeatRuleFieldsL(
    const MPIMRepeatRuleData* aRepeat, // Fields are read from this
    TInt* aInterval, // interval is stored here
    TInt* aFrequency, // frequency is stored here
    TVersitDateTime** aVersitEndDate) // end date is stored here
{
    JELOG2(EPim);
    TBool endExists = EFalse;
    CArrayFix<TPIMField>* repeatFields = aRepeat->GetFieldsL();
    CleanupStack::PushL(repeatFields);
    TInt fieldCount = repeatFields->Count();
    for (TInt i = 0; i < fieldCount; i++)
    {
        switch (repeatFields->At(i))
        {
        case EPIMRepeatRuleFrequency:
        {
            *aFrequency = aRepeat->GetIntL(EPIMRepeatRuleFrequency);
            break;
        }
        case EPIMRepeatRuleInterval:
        {
            *aInterval = aRepeat->GetIntL(EPIMRepeatRuleInterval);
            break;
        }
        case EPIMRepeatRuleEnd:
        {
            endExists = ETrue;
            break;
        }
        default:
        {
            // We ignore other fields
        }
        }
    }
    CleanupStack::PopAndDestroy(repeatFields);
    if (endExists)
    {
        TPIMDate endDate = aRepeat->GetDateL(EPIMRepeatRuleEnd);
        *aVersitEndDate
        = new(ELeave) TVersitDateTime(endDate.DateTime(), TVersitDateTime::EIsUTC);
    }
}
// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::CreateRecurrenceL
// Makes a CVersitRecurrence according to parameters
// -----------------------------------------------------------------------------
//
CVersitRecurrence* CPIMEventPropertyConverter::CreateRecurrenceL(
    TInt aFrequency, TInt aInterval, TVersitDateTime* aVersitEndDate)
{
    JELOG2(EPim);
    CVersitRecurrence* recurrence = NULL;
    switch (aFrequency)
    {
    case EPIMRepeatRuleDaily:
    {
        recurrence
        = new(ELeave) CVersitRecurrenceDaily(aInterval, 0, aVersitEndDate);
        break;
    }
    case EPIMRepeatRuleWeekly:
    {
        recurrence
        = new(ELeave) CVersitRecurrenceWeekly(aInterval, 0, aVersitEndDate, NULL);
        break;
    }
    case EPIMRepeatRuleMonthly:
    {
        recurrence
        = new(ELeave) CVersitRecurrenceMonthlyByDay(
            aInterval, 0, aVersitEndDate, NULL, NULL, NULL);
        break;
    }
    case EPIMRepeatRuleYearly:
    {
        recurrence
        = new(ELeave) CVersitRecurrenceYearlyByDay(aInterval, 0, aVersitEndDate, NULL);
        break;
    }
    default:
    {
        User::Leave(KErrNotSupported);
    }
    }
    return recurrence;
}

// -----------------------------------------------------------------------------
// CPIMEventPropertyConverter::AddPropertyToParserL
// adds a new property value to the parser. NOTE that the property value can be
// of any type and it is taken to ownership within this function.
// -----------------------------------------------------------------------------
//
void CPIMEventPropertyConverter::AddPropertyToParserL(
    CParserPropertyValue* aPropertyValue, const TDesC8& aPropertyName,
    CParserVCalEntity& aParser)
{
    JELOG2(EPim);
    // Add property value to the cleanup stack. It should not be added
    // before this call. This function is an exception and reduces much code
    CleanupStack::PushL(aPropertyValue);
    // Create a new parser property from the property value, its name and
    // array of parameters. If there are no parameters, the aArrayOfParams
    // should be NULL and the parser property will be generated without params
    CParserProperty* property = CParserProperty::NewL(*aPropertyValue,
                                aPropertyName, NULL);
    // property takes ownership of the property value
    CleanupStack::Pop(aPropertyValue);
    // NOTE: property MUST not be pushed to the cleanup stack since the
    // AddPropertyL pushes it right away to the cleanup stack. So, we must not
    // push it here to avoid duplicate stack pointers
    aParser.AddPropertyL(property);
    // Property is now owned by the parser but we do not have to pop it
}

// End of file
