javaextensions/pim/agnadapter/src.s60/cpimagntodoadapter.cpp
branchRCL_3
changeset 19 04becd199f91
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javaextensions/pim/agnadapter/src.s60/cpimagntodoadapter.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,719 @@
+/*
+* 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:  Handles PIM API todo item <-> Agenda Model todo conversions
+ *
+*/
+
+
+// CLASS HEADER
+#include "cpimagntodoadapter.h"
+
+// INTERNAL INCLUDES
+#include "mpimtodoitem.h"
+#include "mpimitemdata.h"
+#include "pimpanics.h"
+#include "pimtypes.h"
+#include "logger.h"
+
+// EXTERNAL INCLUDES
+#include <e32math.h>
+#include <calentry.h>
+#include <calalarm.h>
+
+
+// UNNAMED LOCAL NAMESPACE
+namespace
+{
+// Seconds in a one minute
+const TInt KPIMSecondsInMinute = 60;
+// Maximum length of ToDo item string fields in S60
+const TInt KPIMToDoStringValueMaxLength = 160;
+// Alarm offset for TTime in seconds from the start of the date. This is
+// the default alarm value which is set to the item if the user defined
+// alarm value is too small (meaning that it has been passed to the next
+// day when start of the event occurs
+const TInt KPIMDefaultAlarmInterval = 43200;
+}
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CPIMAgnToDoAdapter* CPIMAgnToDoAdapter::NewL(
+    java::util::FunctionServer* aFuncServer)
+{
+    JELOG2(EPim);
+    CPIMAgnToDoAdapter* self = new(ELeave) CPIMAgnToDoAdapter(aFuncServer);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+}
+
+// destructor
+CPIMAgnToDoAdapter::~CPIMAgnToDoAdapter()
+{
+    JELOG2(EPim);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::CreateItemToAgnL
+// Creates a new Agenda Model To-Do item from a PIM item data.
+// Returns: A To-do item based on PIM item data.
+//          The ownership of the To-do item is transferred to the caller.
+// -----------------------------------------------------------------------------
+//
+CCalEntry* CPIMAgnToDoAdapter::CreateItemToAgnL(const MPIMToDoItem& aItem)
+{
+    JELOG2(EPim);
+    // Create new calendar entry
+    CCalEntry* entry = CreateCalendarEntryLC(CCalEntry::ETodo);
+    // Export entry. No need to reset since this is a new entry
+    ExportItemL(aItem, *entry, EFalse);
+    CleanupStack::Pop(entry);
+    return entry;
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::ReadAgnToItemL
+// Reads an Agenda Model To-do item and converts it to a framework PIM item.
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::ReadAgnToItemL(MPIMToDoItem& aItem, CCalEntry& aEntry)
+{
+    JELOG2(EPim);
+    MPIMItemData& itemData = aItem.ItemData();
+    // Read string fields to PIM API ToDo entry (summary and note)
+    ReadStringFieldsL(itemData, aEntry);
+    // Read integer fields to PIM API ToDo entry (priority and class)
+    ReadIntFieldsL(itemData, aEntry);
+    // Read date fields to PIM API ToDo entry (due and completion date). Alarm
+    // is read here also because it is related to the due date of the item
+    ReadDateFieldsL(itemData, aEntry);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::UpdateItemToAgnL
+// Reads an Agenda Model To-do item and updates it based on the PIM item data.
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::UpdateItemToAgnL(const MPIMToDoItem& aItem,
+        CCalEntry& aEntry)
+{
+    JELOG2(EPim);
+    // Export PIM item data to the native entry. Reset the entry for new data
+    ExportItemL(aItem, aEntry, ETrue);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::ExportItemL
+// (other items were commented in a header)
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::ExportItemL(const MPIMToDoItem& aItem,
+                                     CCalEntry& aEntry, TBool aResetEntry)
+{
+    JELOG2(EPim);
+    if (aResetEntry)
+    {
+        // Reset native entry for exporting new data
+        aEntry.SetSummaryL(KNullDesC());
+        aEntry.SetDescriptionL(KNullDesC());
+        aEntry.SetPriorityL(0);
+        aEntry.SetCompletedL(EFalse, aEntry.CompletedTimeL());
+    }
+
+    // Export item data to the native ToDo calendar entry
+    const MPIMItemData& itemData = aItem.ItemData();
+    CArrayFix<TPIMField>* fields = itemData.FieldsLC();
+
+    // Add default values to the calendar entry
+    AddDefaultValuesToEntryL(itemData, aEntry);
+
+    // Convert each field to the native ToDo calendar entry
+    TInt count = fields->Count();
+    for (TInt i = 0; i < count; i++)
+    {
+        TPIMToDoField field = static_cast<TPIMToDoField>(fields->At(i));
+        ConvertToAgnL(field, aEntry, itemData);
+    }
+    CleanupStack::PopAndDestroy(fields);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::AddDefaultValuesToEntryL
+// (other items were commented in a header)
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::AddDefaultValuesToEntryL(const MPIMItemData& aData,
+        CCalEntry& aEntry) const
+{
+    JELOG2(EPim);
+    // Calendar creates medium priority ToDos by default
+    if (!aData.CountValues(EPIMToDoPriority))
+    {
+        aEntry.SetPriorityL(EPIMToDoNativePriorityMedium);
+    }
+    // Calendar uses private synchronization by default
+    if (!aData.CountValues(EPIMToDoClass))
+    {
+        aEntry.SetReplicationStatusL(CCalEntry::EPrivate);
+    }
+    // Calendar does not support timed ToDo so the time is set to 00:00 o'clock
+    if (!aData.CountValues(EPIMToDoDue))
+    {
+        TTime thisTime;
+        thisTime.HomeTime();
+        // Set time to calendar specific due time. Currently this is the start
+        // of the date. Note that No conversion needed since time is local
+        TCalTime calThisTime;
+        // Set time as local time since acquired above as local time
+        calThisTime.SetTimeLocalL(StartOfDay(thisTime));
+        aEntry.SetStartAndEndTimeL(calThisTime, calThisTime);
+    }
+    if (!aData.CountValues(EPIMToDoCompletionDate) && !aData.CountValues(
+                EPIMToDoCompleted))
+    {
+        aEntry.SetCompletedL(EFalse, aEntry.CompletedTimeL());
+    }
+
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::ReadStringFieldsL
+// (other items were commented in a header)
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::ReadStringFieldsL(MPIMItemData& aData,
+        CCalEntry& aEntry)
+{
+    JELOG2(EPim);
+    // Summary is converted to PIM API ToDo summary field
+    const TDesC& sum = aEntry.SummaryL();
+    if (sum != KNullDesC)
+    {
+        TPIMFieldData fieldData(EPIMToDoSummary, KPIMAttrNone, sum.AllocLC());
+        aData.AddValueL(fieldData);
+        CleanupStack::Pop(); // agnSummary.AllocLC()
+    }
+    // Description is converted to PIM API ToDo note field
+    const TDesC& note = aEntry.DescriptionL();
+    if (note != KNullDesC)
+    {
+        TPIMFieldData fieldData(EPIMToDoNote, KPIMAttrNone, note.AllocLC());
+        aData.AddValueL(fieldData);
+        CleanupStack::Pop(); // AllocLC
+    }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::ReadIntFieldsL
+// (other items were commented in a header)
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::ReadIntFieldsL(MPIMItemData& aData, CCalEntry& aEntry)
+{
+    JELOG2(EPim);
+    // Convert synchornization field to PIM API. The default value is private
+    // and unrecognized priority values are mapped also to private due to
+    // security reasons
+    TPIMToDoClassValue value = EPIMToDoClassPrivate;
+    const CCalEntry::TReplicationStatus status = aEntry.ReplicationStatusL();
+    if (status == CCalEntry::EOpen)
+    {
+        // Open is mapped as public synhronization
+        value = EPIMToDoClassPublic;
+    }
+    else if (status == CCalEntry::ERestricted)
+    {
+        // Open is mapped as user confidential synhronization
+        value = EPIMToDoClassConfidential;
+    }
+    // Note that boolean and integer fields must be identified in the constructor
+    TPIMFieldData classData(EPIMToDoClass, EPIMFieldInt, KPIMAttrNone, value);
+    aData.AddValueL(classData);
+
+    // Default value is zero acording to vCalendar specification. PIM API default
+    // priority is medium which indicates normal native priority
+    // See common/pimtodo.h for platform-specific native priorities.
+    TUint nativePriority = aEntry.PriorityL();
+    TPIMToDoPriority priority = EPIMToDoPriorityMedium;
+    if (nativePriority == EPIMToDoNativePriorityHigh)
+    {
+        // Native priority value High is mapped to value 1
+        priority = EPIMToDoPriorityHigh;
+    }
+    else if (nativePriority == EPIMToDoNativePriorityLow)
+    {
+        // Native priority value Low is mapped to value 7
+        priority = EPIMToDoPriorityLow;
+    }
+    // Note that boolean and integer fields must be identified in the constructor
+    TPIMFieldData
+    prData(EPIMToDoPriority, EPIMFieldInt, KPIMAttrNone, priority);
+    aData.AddValueL(prData);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::ReadDateFieldsL
+// (other items were commented in a header)
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::ReadDateFieldsL(MPIMItemData& aData, CCalEntry& aEntry)
+{
+    JELOG2(EPim);
+    TTime nullTime = Time::NullTTime();
+    // The Agenda todo entry end field is the due date
+    TTime due(aEntry.EndTimeL().TimeLocalL());
+    if (due != nullTime)
+    {
+        // Set due to the PIM API specific due date, in this case, the start of date
+        // Note that PIM API uses times as UTC times so the due date must be in
+        // correct format. Previously requested as local time -> do not change
+        TPIMDate pimDueDate(StartOfDay(due));
+        // Date must be converted UTC time because acquired as local above
+        ConvertTimeL(pimDueDate, EPIMDateUTC);
+        TPIMFieldData dueFieldData(EPIMToDoDue, KPIMAttrNone, pimDueDate);
+        aData.AddValueL(dueFieldData);
+
+        // Get alarm. Ownership is transferred to the caller. Alarm cannot be set
+        // if the due date is not set because the calculation is done as an offset
+        // from the ToDo due date.
+        CCalAlarm* calAlarm = aEntry.AlarmL();
+        if (calAlarm)
+        {
+            TTimeIntervalMinutes nativeValue = calAlarm->TimeOffset();
+            // The alarm is not needed anymore so it can be deleted
+            delete calAlarm;
+            calAlarm = NULL;
+            // Change the time to the start of the due date
+            TTime startOfDayLocal(StartOfDay(due));
+            // Calculate the difference from the start of due date and start time including
+            // the original alarm offset which was previously read
+            TTimeIntervalMinutes temp(0);
+            User::LeaveIfError(startOfDayLocal.MinutesFrom(due, temp));
+            // Since it is not possible to substract TTimeIntervalMinutes
+            // from TTime (probably a Symbian error), the difference has
+            // to be calculated using the following way...
+            TInt alarm = (nativeValue.Int() + temp.Int()) * KPIMSecondsInMinute;
+            // Add alarm value to the item
+            TPIMFieldData fieldData(EPIMToDoExtAlarm, EPIMFieldInt,
+                                    KPIMAttrNone, alarm);
+            // Add value to the PIM item data
+            aData.AddValueL(fieldData);
+        }
+    }
+
+    // Completion date. If the item has a completion date, the item is then completed
+    // and completed flag is set to true in PIM API. Null time if not crossed out.
+    TTime completed = aEntry.CompletedTimeL().TimeUtcL();
+    if (completed != nullTime)
+    {
+        TPIMFieldData dateData(EPIMToDoCompletionDate, KPIMAttrNone, completed);
+        aData.AddValueL(dateData);
+        // Note that boolean and integer fields must be identified in the constructor
+        TPIMFieldData flag(EPIMToDoCompleted, EPIMFieldBoolean, KPIMAttrNone,
+                           ETrue);
+        aData.AddValueL(flag);
+    }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::ConvertToAgnL
+// Makes the conversion from framework PIM item data field to To-do item field.
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::ConvertToAgnL(TPIMToDoField aField, // The field to be converted
+                                       CCalEntry& aEntry, const MPIMItemData& aItem)
+{
+    JELOG2(EPim);
+    TInt amount = aItem.CountValues(aField);
+    for (TInt index = 0; index < amount; index++)
+    {
+        switch (aField)
+        {
+        case EPIMToDoCompletionDate: // fallthrough
+        case EPIMToDoDue:
+        {
+            ConvertDateToAgnL(aField, index, aEntry, aItem);
+            break;
+        }
+        case EPIMToDoSummary: // fallthrough
+        case EPIMToDoNote:
+        {
+            ConvertStringToAgnL(aField, index, aEntry, aItem);
+            break;
+        }
+        case EPIMToDoClass: // fallthrough
+        case EPIMToDoExtAlarm:
+        case EPIMToDoPriority:
+        {
+            ConvertIntToAgnL(aField, index, aEntry, aItem);
+            break;
+        }
+        case EPIMToDoCompleted:
+        {
+            ConvertBooleanToAgnL(aField, index, aEntry, aItem);
+            break;
+        }
+        case EPIMToDoUid: // fallthrough
+        case EPIMToDoRevision:
+        {
+            // nothing
+            break;
+        }
+        default:
+        {
+            __ASSERT_DEBUG(EFalse, User::Panic(KPIMPanicCategory,
+                                               EPIMPanicUnsupportedField));
+        }
+        }
+    }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::ConvertDateToAgnL
+// Makes date conversion from framework PIM item data field to To-do item field.
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::ConvertDateToAgnL(TPIMToDoField aField, // Date field to be converted
+        TInt aIndex, // Index of the date field
+        CCalEntry& aEntry, const MPIMItemData& aItem) // The PIM item to read the field from
+{
+    JELOG2(EPim);
+    const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
+    const TPIMDate& date = fieldData.DateValue();
+    switch (aField)
+    {
+    case EPIMToDoDue:
+    {
+        // Because undated to-dos are possible, the due date can be set
+        // to a null value.
+        if (date != Time::NullTTime() && !IsDateInValidAgendaRange(date))
+        {
+            User::Leave(KErrAbort);
+        }
+        // Java dates cannot be set to native null TTime
+        else
+        {
+            // Convert due date and time to calendar specific due time
+            // Note that PIM API dates are in UTC time format -> convert
+            TTime dueDate(date);
+            ConvertTimeL(dueDate, EPIMDateLocal);
+            // Set time to native entry. Note that the time is local
+            TCalTime calDate;
+            calDate.SetTimeLocalL(StartOfDay(dueDate));
+            aEntry.SetStartAndEndTimeL(calDate, calDate);
+        }
+        break;
+    }
+    case EPIMToDoCompletionDate:
+    {
+        if (date != Time::NullTTime())
+        {
+            __ASSERT_ALWAYS(IsDateInValidAgendaRange(date), User::Leave(
+                                KErrAbort));
+            TCalTime calDate;
+            calDate.SetTimeUtcL(date);
+            aEntry.SetCompletedL(ETrue, calDate);
+        }
+        else
+        {
+            aEntry.SetCompletedL(EFalse, aEntry.CompletedTimeL());
+        }
+        break;
+    }
+    default:
+    {
+        __ASSERT_DEBUG(EFalse, User::Panic(KPIMPanicCategory,
+                                           EPIMPanicUnsupportedField));
+    }
+    }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::ConvertStringToAgnL
+// Makes string conversion from framework PIM item data field to To-do item field
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::ConvertStringToAgnL(TPIMToDoField aField, // String field to be converted
+        TInt aIndex, // Index of the date field
+        CCalEntry& aEntry, // The Agenda Model entry
+        const MPIMItemData& aItem) // The PIM item to read the field from
+{
+    JELOG2(EPim);
+    const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
+    const TDesC& string = fieldData.StringValue();
+
+    // Check that string is not too long
+    __ASSERT_ALWAYS(string.Length() <= KPIMToDoStringValueMaxLength,
+                    User::Leave(KErrTooBig));
+
+    switch (aField)
+    {
+    case EPIMToDoSummary:
+    {
+        aEntry.SetSummaryL(string);
+        break;
+    }
+    case EPIMToDoNote:
+    {
+        aEntry.SetDescriptionL(string);
+        break;
+    }
+    default:
+    {
+        // Should not happen
+    }
+    }
+
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::ConvertIntToAgnL
+// Makes int conversion from framework PIM item data field to To-do item field.
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::ConvertIntToAgnL(TPIMToDoField aField, // Int field to be converted
+        TInt aIndex, // Index of the date field
+        CCalEntry& aEntry, // The Agenda model entry typecasted to a Todo item
+        const MPIMItemData& aItemData) // The PIM item to read the field from
+{
+    JELOG2(EPim);
+    const TPIMFieldData fieldData = aItemData.ValueL(aField, aIndex);
+    switch (aField)
+    {
+    case EPIMToDoPriority:
+    {
+        TInt intField = fieldData.IntegerValue();
+
+        if ((EPIMToDoPriorityHigh <= intField) && (intField
+                < EPIMToDoPriorityMedium))
+        {
+            aEntry.SetPriorityL(EPIMToDoNativePriorityHigh);
+        }
+        else if ((EPIMToDoPriorityMedium <= intField) && (intField
+                 < EPIMToDoPriorityLow))
+        {
+            aEntry.SetPriorityL(EPIMToDoNativePriorityMedium);
+        }
+        else if ((EPIMToDoPriorityLow <= intField) && (intField
+                 <= EPIMToDoPriorityMaxValue))
+        {
+            aEntry.SetPriorityL(EPIMToDoNativePriorityLow);
+        }
+        else
+        {
+            // From requirement specification: Imported to-do items with
+            // priority set to zero must be mapped to the native priority
+            // value Medium.
+            aEntry.SetPriorityL(EPIMToDoNativePriorityMedium);
+        }
+        break;
+    }
+    case EPIMToDoClass:
+    {
+        CCalEntry::TReplicationStatus replicationStatus = CCalEntry::EPrivate;
+
+        // Single value assumed
+        TInt classValue = fieldData.IntegerValue();
+
+        switch (classValue)
+        {
+        case EPIMToDoClassPrivate:
+        {
+            replicationStatus = CCalEntry::EPrivate;
+            break;
+        }
+        case EPIMToDoClassConfidential:
+        {
+            replicationStatus = CCalEntry::ERestricted;
+            break;
+        }
+        case EPIMToDoClassPublic:
+        {
+            replicationStatus = CCalEntry::EOpen;
+            break;
+        }
+        default:
+        {
+            User::Leave(KErrArgument);
+            break;
+        }
+        }
+        aEntry.SetReplicationStatusL(replicationStatus);
+        break;
+    }
+    case EPIMToDoExtAlarm:
+    {
+        CCalAlarm* agnAlarm = CCalAlarm::NewL();
+        CleanupStack::PushL(agnAlarm);
+        agnAlarm->SetTimeOffset(AlarmOffsetL(aItemData, aEntry));
+        aEntry.SetAlarmL(agnAlarm);
+        CleanupStack::PopAndDestroy(agnAlarm);
+        break;
+    }
+    default:
+    {
+        // Should not happen
+        __ASSERT_DEBUG(EFalse, User::Invariant());
+    }
+    }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::ConvertBooleanToAgnL
+// Makes boolean conversion from framework PIM item data field to To-do item field
+// -----------------------------------------------------------------------------
+//
+void CPIMAgnToDoAdapter::ConvertBooleanToAgnL(TPIMToDoField aField, // Boolean field to be converted
+        TInt aIndex, // Index of the date field
+        CCalEntry& aEntry, // The Agenda model entry typecasted to a Todo item
+        const MPIMItemData& aItem) // The PIM item to read the field from
+{
+    JELOG2(EPim);
+    const TPIMFieldData fieldData = aItem.ValueL(aField, aIndex);
+    TBool booleanField = fieldData.BooleanValue();
+
+    if (booleanField) // completed flag is set to value TRUE
+    {
+        // Check if the completed date field is present
+        if (aItem.CountValues(EPIMToDoCompletionDate) == 0)
+        {
+            // If completed date is not present, use the current time.
+            TTime currentTime;
+            currentTime.HomeTime();
+            TCalTime calCurrentTime;
+            // Set time as local time since acquired above as local time
+            calCurrentTime.SetTimeLocalL(currentTime);
+            aEntry.SetCompletedL(ETrue, calCurrentTime);
+        }
+        else
+        {
+            TPIMFieldData completionData = aItem.ValueL(EPIMToDoCompletionDate,
+                                           aIndex);
+            const TPIMDate& date = completionData.DateValue();
+            if (date != Time::NullTTime())
+            {
+                TCalTime calDate;
+                calDate.SetTimeUtcL(date);
+                aEntry.SetCompletedL(ETrue, calDate);
+            }
+            else
+            {
+                // If completed date is set to null time, use the current time.
+                TTime currentTime;
+                currentTime.HomeTime();
+                TCalTime calCurrentTime;
+                // Set time as local time since acquired above as local time
+                calCurrentTime.SetTimeLocalL(currentTime);
+                aEntry.SetCompletedL(ETrue, calCurrentTime);
+            }
+        }
+    }
+    else // completed flag is set to value FALSE
+    {
+        aEntry.SetCompletedL(EFalse, aEntry.CompletedTimeL());
+    }
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::AlarmOffsetL
+// Calculates PIM alarm offset for native Calendar entry
+// The offset calculation is done by calculating the difference between the
+// due date and the alarm offset. After we know the alarm date and time we
+// calculate difference between calender specific todo due date (which now is
+// 00:00)
+//
+// For example:
+//
+// If our due time is 23:00 and the alarm offset is 900 seconds before it.
+// Then the alarm should launch at 22:45 at the same day. So, the offset which
+// we have to write to the native alarm is the difference between 00:00 and 22:45
+// which is a negative value because the alarm rises in the future. This all is
+// done because the calendar understands only the date of the due date and not the
+// exact time of it. The time is ignored and set to 00:00 by default.
+// -----------------------------------------------------------------------------
+//
+TTimeIntervalMinutes CPIMAgnToDoAdapter::AlarmOffsetL(
+    const MPIMItemData& aItemData, CCalEntry& aEntry)
+{
+    JELOG2(EPim);
+    // Note that start time must be set before alarm can be calculated
+    // Add start to the item so alarm can be properly converted. The
+    // native entry does not accept alarm value if start is not present
+    // Due has been already set to default time (current home time) if
+    // ToDo due field is not present in the field so start should be present
+    if (!aItemData.CountValues(EPIMToDoDue))
+    {
+        User::Leave(KErrArgument);
+    }
+    else
+    {
+        ConvertDateToAgnL(EPIMToDoDue, 0, aEntry, aItemData);
+    }
+
+    __ASSERT_DEBUG(aEntry.StartTimeL().TimeUtcL() != Time::NullTTime(),
+                   User::Panic(KPIMPanicCategory, EPIMPanicInvalidState));
+
+    // Get alarm value from the Java item. There should be only one alarm
+    // value supported by the PIM API because native entries do not support
+    // multiple alarm values.
+    const TPIMFieldData alarmData = aItemData.ValueL(EPIMToDoExtAlarm, 0);
+    TInt value = alarmData.IntegerValue();
+
+    // Count the alarm value from the start date of the event
+    TTime entryStart = aEntry.StartTimeL().TimeLocalL();
+    const TPIMFieldData dateData = aItemData.ValueL(EPIMToDoDue, 0);
+    TPIMDate dueDate(dateData.DateValue());
+    ConvertTimeL(dueDate, EPIMDateLocal);
+    TTimeIntervalSeconds temp(0);
+    User::LeaveIfError(entryStart.SecondsFrom(dueDate, temp));
+
+    // Add difference between PIM API start and start which has been
+    // converted to the item (in case if the date has been changed, it is
+    // reflected here)
+    value += temp.Int();
+
+    // Check that if the alarm has passed to the following day. In this case,
+    // the alarm is transferred back to 12 o'clock of the current start date
+    TTime alarmTime(entryStart - TTimeIntervalSeconds(value));
+    // Temporary date. This date is used when calculating if the alarm
+    // value has passed to the following date.
+    TTime startOfNextDay(StartOfDay(dueDate + TTimeIntervalDays(1)));
+    if (alarmTime >= startOfNextDay)
+    {
+        alarmTime = StartOfDay(entryStart);
+        alarmTime += TTimeIntervalSeconds(KPIMDefaultAlarmInterval);
+        User::LeaveIfError(entryStart.SecondsFrom(alarmTime, temp));
+        value = temp.Int();
+    }
+    // Convert seconds to minutes
+    return TTimeIntervalMinutes(value / KPIMSecondsInMinute);
+}
+
+// -----------------------------------------------------------------------------
+// CPIMAgnToDoAdapter::CPIMAgnToDoAdapter
+// -----------------------------------------------------------------------------
+//
+CPIMAgnToDoAdapter::CPIMAgnToDoAdapter(java::util::FunctionServer* aFuncServer) :
+        CPIMAgnItemAdapter(aFuncServer)
+{
+    JELOG2(EPim);
+}
+
+// End of File