utilsrecurrence.cpp

来自「funambol window mobile客户端源代码」· C++ 代码 · 共 1,256 行 · 第 1/3 页

CPP
1,256
字号
/*
 * Funambol is a mobile platform developed by Funambol, Inc.
 * Copyright (C) 2003 - 2007 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include <stdio.h>
#include <windows.h>
#include <Winbase.h>
#include "base/Log.h"
#include "base/util/utils.h"
#include "base/base64.h"
#include "base/util/XMLProcessor.h"
#include "base/stringUtils.h"

#include "pim/Utils.h"
#include "pim/UtilsRecurrence.h"
#include "pim/RecurrenceException.h"
#include "pim/AppointmentBuilder.h"
#include "pim/MAPIUtils.h"



/**
 * Array of recurring fields names for SIF format.
 * It's used by both appointment and task items.
 * @note Don't change the order of these properties!
 */
const wchar_t* recurrenceFields[] = {

    {L"RecurrenceType"                     },                // Returns or set a RecurrenceType. values are orRecursDaily...
    {L"PatternStartDate"                   },                // Returns or sets the start date of the recurrence.
    {L"PatternEndDate"                     },                // Returns or sets the end date of the recurrence.
    {L"StartTime"                          },
    {L"EndTime"                            },
    {L"NoEndDate"                          },                // True if there is no end date. True is 1.
    {L"Occurrences"                        },                // Return or sets the number of the occurrences of the recurrence.
    {L"Interval"                           },                // Is the interval of the recurrence. If RecurrenceType is olRecursDaily, event occurs every <Interval> day. If olRecursWeekly, event occurs every <inteval> week..
    {L"DayOfWeekMask"                      },                // The combination days of the week constants (i. e. event recurring on Monday and Wednesday. The DayOfWeekMask should be olMonday + olWednesday)
    {L"DayOfMonth"                         },                // Returns or sets the single day of the month from 1 to 31.
    {L"Instance"                           },                // Returns or sets the ordinal number of the day, week, month.
    //{L"RecurringDuration"                  },
    {L"MonthOfYear"                        },                // Returns or sets the month of year.
    
    {NULL}
};



// ************* remove... ******************
#define STRING_NO_RECURRENCE    TEXT("<RecurrenceType/><Interval/><MonthOfYear/><DayOfMonth/><DayOfWeekMask/><Instance/><PatternStartDate/><NoEndDate/><PatternEndDate/><Occurrences/><Exceptions/>")
#define EXCLUDE_DATE            TEXT("ExcludeDate")
#define INCLUDE_DATE            TEXT("IncludeDate")

int convertDayOfWeekMaskBackward(int dayOfWeekMaskSent) {
    int dayOfWeekMask = 0;
    if ((dayOfWeekMaskSent % 2) != 0) {
        dayOfWeekMask = dayOfWeekMaskSent >> 1;
        dayOfWeekMask += 64;
    }
    else {
        dayOfWeekMask = dayOfWeekMaskSent >> 1;
    }
    return dayOfWeekMask;
}
int convertDayOfWeekMaskForward(int dayOfWeekMaskSent) {
    int dayOfWeekMask = 0;
    if (dayOfWeekMaskSent >= 64) {
        dayOfWeekMask = dayOfWeekMaskSent << 1;
        dayOfWeekMask -= 127;
    }
    else {
        dayOfWeekMask = dayOfWeekMaskSent << 1;
    }
    return dayOfWeekMask;
}

wstring getRecurrenceTags(IRecurrencePattern* pRecurrence, VARIANT_BOOL isRecurring,
                          int x, int y, OlDefaultFolders olFolder, DATE startdate, BOOL isAllDay) {

    wstring appointmentStringItem = TEXT("");
    wchar_t tempDate [DIM_LOCAL_TEMP];
    VARIANT_BOOL variantBool = NULL; // 0==false -1==true

    if (isRecurring == FALSE) {
        return STRING_NO_RECURRENCE;
    }

    int z = 0;
    BOOL changeDay = FALSE, isBackward = FALSE;
    BOOL changeYearBackward = FALSE, changeYearForward = FALSE;

    double toCompare = MAX_DATE_DOUBLE;
    double toCompare4000 = MAX_DATE_DOUBLE_4000;

    BSTR element        = NULL      ;
    long elementLong    = 0         ;

    DATE date           = NULL      ;
    wstring element_s;

    long            recurrenceType = 0,
                    interval       = 0,
                    monthOfYear    = 0,
                    dayOfMonth     = 0,
                    dayOfWeekMask  = 0,
                    instance       = 0;

    pRecurrence->get_RecurrenceType(&recurrenceType);
    pRecurrence->get_Interval(&interval);
    pRecurrence->get_MonthOfYear(&monthOfYear);
    pRecurrence->get_DayOfMonth(&dayOfMonth);
    pRecurrence->get_Instance(&instance);
    pRecurrence->get_DayOfWeekMask(&dayOfWeekMask);

    //
    // Modification to get right information about changing day, month...
    //
    TIME_ZONE_INFORMATION tmz;
    int k = GetTimeZoneInformation(&tmz);

    z = (x-y) < 0 ? (x-y)*(-1) : (x-y) ;

    //
    // Change day?
    //
    changeDay = z > 12 ? TRUE : FALSE;

    if (isAllDay)
        changeDay = FALSE;

    if (changeDay) {
        if (tmz.Bias < 0)
            isBackward = TRUE;
        else
            isBackward = FALSE;
    }

    //
    // RecurrenceType
    //
    if (recurrenceType < 0) {
        recurrenceType = 0;
    }
    wsprintf(tempDate, TEXT("%i"), recurrenceType);
    appointmentStringItem  = appointmentStringItem + TEXT("<RecurrenceType>") + tempDate + TEXT("</RecurrenceType>");

    //
    // Interval
    //
    wsprintf(tempDate, TEXT("%i"), interval);
    appointmentStringItem  = appointmentStringItem + TEXT("<Interval>") + tempDate + TEXT("</Interval>");

    //
    // Day of Month
    //
    if (dayOfMonth != 0) {

        if (changeDay) {
            if (isBackward) {
                dayOfMonth = dayOfMonth - 1;
                if (dayOfMonth == 0) {
                    if (monthOfYear == 5 || monthOfYear == 7 || monthOfYear == 10) {
                        // if May, July, October the month before has 30 days
                        dayOfMonth = 30;
                    } else {
                        dayOfMonth = 31;
                    }
                    changeYearBackward = TRUE;
                }
            } else { // is
                dayOfMonth = dayOfMonth + 1;
                if (dayOfMonth >  31  ||
                      (dayOfMonth == 31 &&
                        (monthOfYear == 4 || monthOfYear == 6 || monthOfYear == 9)
                       )
                    ) {
                    dayOfMonth = 1;
                    changeYearForward = TRUE;
                }
            }

        } //endif

        wsprintf(tempDate, TEXT("%i"), dayOfMonth);
        appointmentStringItem  = appointmentStringItem + TEXT("<DayOfMonth>") + tempDate + TEXT("</DayOfMonth>");
    } else {
        appointmentStringItem  = appointmentStringItem + TEXT("<DayOfMonth>0</DayOfMonth>");
    }

    //
    // Month of Year
    //
    if (monthOfYear != 0) {
        if (changeYearBackward) {
            monthOfYear = monthOfYear - 1;
            if (monthOfYear == 0) {
                monthOfYear = 12;
            }
        } else if (changeYearForward) {
            monthOfYear = monthOfYear + 1;
            if (monthOfYear > 12) {
                monthOfYear = 1;
            }
        }
        wsprintf(tempDate, TEXT("%i"), monthOfYear);
        appointmentStringItem  = appointmentStringItem + TEXT("<MonthOfYear>") + tempDate + TEXT("</MonthOfYear>");
    } else {
        appointmentStringItem  = appointmentStringItem + TEXT("<MonthOfYear>0</MonthOfYear>");
    }
    //
    // DayOfWeekMask
    //
    if (dayOfWeekMask != 0) {
        if (changeDay) {
            // do not change week mask
            if (isBackward) {
                dayOfWeekMask = convertDayOfWeekMaskBackward(dayOfWeekMask);
            } else {
                dayOfWeekMask = convertDayOfWeekMaskForward(dayOfWeekMask);
            }
        }
        wsprintf(tempDate, TEXT("%i"), dayOfWeekMask);
        appointmentStringItem  = appointmentStringItem + TEXT("<DayOfWeekMask>") + tempDate + TEXT("</DayOfWeekMask>");
    } else {
        appointmentStringItem  = appointmentStringItem + TEXT("<DayOfWeekMask>0</DayOfWeekMask>");
    }

    //
    // Instance
    //
    if (instance != 0) {
        wsprintf(tempDate, TEXT("%i"), instance);
        appointmentStringItem  = appointmentStringItem + TEXT("<Instance>") + tempDate + TEXT("</Instance>");
    } else {
        appointmentStringItem  = appointmentStringItem + TEXT("<Instance>0</Instance>");
    }

    //
    // Pattern Start Date
    //
    pRecurrence->get_PatternStartDate(&date);
    wsprintf(tempDate, TEXT(""));
    toCompare = MAX_DATE_DOUBLE;

    //
    // We use the start date to avoid every problem
    //
    if (date != toCompare && date < toCompare4000 ) {
        if (isAllDay) {
            doubleToSystemTimeBirthday(tempDate, startdate);
        } else {
            doubleToSystemTime(tempDate, startdate);
        }
        //doubleToSystemTime(tempDate, date);

    }
    appointmentStringItem  = appointmentStringItem + TEXT("<PatternStartDate>") + tempDate + TEXT("</PatternStartDate>");

    //
    // No End Date
    //
    pRecurrence->get_NoEndDate(&variantBool);
    wsprintf(tempDate, TEXT("%i"), variantBool);
    normalizeBoolean(tempDate);
    appointmentStringItem  = appointmentStringItem + TEXT("<NoEndDate>") + tempDate + TEXT("</NoEndDate>");

    //
    // Pattern End Date
    //
    pRecurrence->get_PatternEndDate(&date);
    wsprintf(tempDate, TEXT(""));
    toCompare = MAX_DATE_DOUBLE;
    if (date != toCompare && date < toCompare4000 ) {
        if (startdate) {
            // Fix for PatternEndDate (since v.6.5.6):
            // We need the exact date+time when the last occurrence starts, so we get the
            // time (hours) from startdate and add it to the patternEndDate midnight.
            double hours = startdate - (int)startdate;
            date = (int)date + hours;
        }
        doubleToSystemTime(tempDate, date);
    }
    appointmentStringItem  = appointmentStringItem + TEXT("<PatternEndDate>") + tempDate + TEXT("</PatternEndDate>");

    //
    // Occurrences
    //
    pRecurrence->get_Occurrences(&elementLong);
    if (elementLong < 0) {
        elementLong = 0;
    }
    wsprintf(tempDate, TEXT("%i"), elementLong);
    appointmentStringItem  = appointmentStringItem + TEXT("<Occurrences>") + tempDate + TEXT("</Occurrences>");

    //
    // ---------------- EXCEPTIONS for calendar only ---------
    //

    if (olFolder == olFolderCalendar) {
        if (isRecurring == -1) {
            wstring exceptionItems = createExceptions(pRecurrence, startdate, isAllDay);
            appointmentStringItem += exceptionItems;
        } else {
            appointmentStringItem += TEXT("<Exceptions/>");
        }
    } else if (olFolder == olFolderTasks) {
        //
        // Exceptions in POOM tasks are not permitted!!
        //
        appointmentStringItem += TEXT("<Exceptions/>");
    }

    //
    // ---------------- END EXCEPTIONS ------------------------
    //

    return appointmentStringItem;

}

/*
* Modificated exception creation from client to server.
* The normalization is done in the begin sync process. At this point the items that are
* here should not have any exceptions appointments excepts deletions
*/
wstring createExceptions(IRecurrencePattern* pRecurrence, DATE startdate, BOOL isAllDay) {

    IExceptions* pExceptions;
    int numExceptions;

    pRecurrence->get_Exceptions(&pExceptions);
    pExceptions->get_Count(&numExceptions);

    wstring exceptions = TEXT("<Exceptions>");

    for (int i = 0; i < numExceptions; i++) {
        IException* pException;
        pExceptions->Item(i + 1, &pException);
        wstring exception = createException(pException, startdate, isAllDay);
        exceptions += TEXT("<ExcludeDate>");
        exceptions += exception;
        exceptions += TEXT("</ExcludeDate>");
        pException->Release();
    }

    pExceptions->Release();

    // the exceptions if exists are only in exclude date and so deleted and never created
    exceptions +=  TEXT("<IncludeDate/>");

    exceptions +=  TEXT("</Exceptions>");

    return exceptions;
}

wstring createException(IException* pException, DATE start_date, BOOL isAllDay) {

    wstring exceptionItem = TEXT("");
    DATE originalDate = 0;
    VARIANT_BOOL varBool; // -1 = TRUE, 0 = FALSE
    wchar_t tempDate [DIM_LOCAL_TEMP];

    pException->get_OriginalDate(&originalDate);

    DATE offset = (start_date) - ((long)start_date) ;
    originalDate += offset;
    if (isAllDay) {
        doubleToSystemTimeBirthday(tempDate, originalDate);    // YYYY-MM-DD
    }
    else {
        doubleToSystemTime(tempDate, originalDate);
    }

    // if the recurrence is deleted get the delation and go exit
    pException->get_Deleted(&varBool);
    if (varBool == -1) {
        exceptionItem = wstring(tempDate);
    } else {
        LOG.info("Warning: exception in date %s is not deleted.", tempDate);
    }
    return exceptionItem;
}

/**
 * Parse the recurrence tags in the item sent from server to client.
 *
 * @param pRecurrence       the POOM object to fill
 * @param ptrData           the SIF item to parse
 * @param recurrenceStart   the start date of the event or task

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?