Back to index

lightning-sunbird  0.9+nobinonly
calRecurrenceDateSet.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Oracle Corporation code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  *  Oracle Corporation
00019  * Portions created by the Initial Developer are Copyright (C) 2004
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
00024  *   Philipp Kewisch <mozilla@kewis.ch>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "calRecurrenceDateSet.h"
00041 
00042 #include "calDateTime.h"
00043 #include "calIItemBase.h"
00044 #include "calIEvent.h"
00045 
00046 #include "calICSService.h"
00047 
00048 #ifndef MOZILLA_1_8_BRANCH
00049 #include "nsIClassInfoImpl.h"
00050 #endif
00051 
00052 extern "C" {
00053     #include "ical.h"
00054 }
00055 
00056 NS_IMPL_ISUPPORTS2_CI(calRecurrenceDateSet, calIRecurrenceItem, calIRecurrenceDateSet)
00057 
00058 calRecurrenceDateSet::calRecurrenceDateSet()
00059     : mImmutable(PR_FALSE),
00060       mIsNegative(PR_FALSE),
00061       mSorted(PR_FALSE)
00062 {
00063 }
00064 
00065 NS_IMETHODIMP
00066 calRecurrenceDateSet::GetIsMutable(PRBool *aResult)
00067 {
00068     NS_ENSURE_ARG_POINTER(aResult);
00069 
00070     *aResult = !mImmutable;
00071     return NS_OK;
00072 }
00073 
00074 NS_IMETHODIMP
00075 calRecurrenceDateSet::MakeImmutable()
00076 {
00077     if (mImmutable)
00078         return NS_ERROR_FAILURE; // XXX another error code
00079 
00080     mImmutable = PR_TRUE;
00081     return NS_OK;
00082 }
00083 
00084 NS_IMETHODIMP
00085 calRecurrenceDateSet::Clone(calIRecurrenceItem **_retval)
00086 {
00087     nsresult rv;
00088 
00089     calRecurrenceDateSet *crds = new calRecurrenceDateSet;
00090     if (!crds)
00091         return NS_ERROR_OUT_OF_MEMORY;
00092 
00093     crds->mIsNegative = mIsNegative;
00094 
00095     for (int i = 0; i < mDates.Count(); i++) {
00096         nsCOMPtr<calIDateTime> date;
00097         rv = mDates[i]->Clone(getter_AddRefs(date));
00098         NS_ENSURE_SUCCESS(rv, rv);
00099 
00100         crds->mDates.AppendObject(date);
00101     }
00102 
00103     crds->mSorted = mSorted;
00104 
00105     NS_ADDREF(*_retval = crds);
00106     return NS_OK;
00107 }
00108 
00109 /* attribute boolean isNegative; */
00110 NS_IMETHODIMP
00111 calRecurrenceDateSet::GetIsNegative(PRBool *_retval)
00112 {
00113     NS_ENSURE_ARG_POINTER(_retval);
00114 
00115     *_retval = mIsNegative;
00116     return NS_OK;
00117 }
00118 
00119 NS_IMETHODIMP
00120 calRecurrenceDateSet::SetIsNegative(PRBool aIsNegative)
00121 {
00122     if (mImmutable)
00123         return NS_ERROR_FAILURE; // XXX CAL_ERROR_ITEM_IS_IMMUTABLE
00124 
00125     mIsNegative = aIsNegative;
00126     return NS_OK;
00127 }
00128 
00129 /* readonly attribute boolean isFinite; */
00130 NS_IMETHODIMP
00131 calRecurrenceDateSet::GetIsFinite(PRBool *_retval)
00132 {
00133     NS_ENSURE_ARG_POINTER(_retval);
00134     *_retval = PR_TRUE;
00135     return NS_OK;
00136 }
00137 
00138 NS_IMETHODIMP
00139 calRecurrenceDateSet::GetDates(PRUint32 *aCount, calIDateTime ***aDates)
00140 {
00141     if (mDates.Count() == 0) {
00142         *aDates = nsnull;
00143         *aCount = 0;
00144         return NS_OK;
00145     }
00146 
00147     EnsureSorted();
00148         
00149     calIDateTime **dates = (calIDateTime **) nsMemory::Alloc(sizeof(calIDateTime*) * mDates.Count());
00150     if (!dates)
00151         return NS_ERROR_OUT_OF_MEMORY;
00152 
00153     for (int i = 0; i < mDates.Count(); i++) {
00154         NS_ADDREF(dates[i] = mDates[i]);
00155     }
00156 
00157     *aDates = dates;
00158     *aCount = mDates.Count();
00159 
00160     return NS_OK;
00161 }
00162 
00163 NS_IMETHODIMP
00164 calRecurrenceDateSet::SetDates(PRUint32 aCount, calIDateTime **aDates)
00165 {
00166     NS_ENSURE_ARG_POINTER(aDates);
00167 
00168     mDates.Clear();
00169     for (PRUint32 i = 0; i < aCount; i++) {
00170         mDates.AppendObject(aDates[i]);
00171     }
00172 
00173     mSorted = PR_FALSE;
00174 
00175     return NS_OK;
00176 }
00177 
00178 NS_IMETHODIMP
00179 calRecurrenceDateSet::AddDate(calIDateTime *aDate)
00180 {
00181     NS_ENSURE_ARG_POINTER(aDate);
00182 
00183     mDates.AppendObject(aDate);
00184 
00185     mSorted = PR_FALSE;
00186 
00187     return NS_OK;
00188 }
00189 
00190 static int PR_CALLBACK
00191 calDateTimeComparator (calIDateTime *aElement1,
00192                        calIDateTime *aElement2,
00193                        void *aData)
00194 {
00195     PRInt32 result;
00196     aElement1->Compare(aElement2, &result);
00197     return result;
00198 }
00199 
00200 void
00201 calRecurrenceDateSet::EnsureSorted()
00202 {
00203     if (!mSorted) {
00204         mDates.Sort(calDateTimeComparator, nsnull);
00205         mSorted = PR_TRUE;
00206     }
00207 }
00208 
00209 NS_IMETHODIMP
00210 calRecurrenceDateSet::GetNextOccurrence(calIDateTime *aStartTime,
00211                                         calIDateTime *aOccurrenceTime,
00212                                         calIDateTime **_retval)
00213 {
00214     NS_ENSURE_ARG_POINTER(aStartTime);
00215     NS_ENSURE_ARG_POINTER(aOccurrenceTime);
00216     NS_ENSURE_ARG_POINTER(_retval);
00217 
00218     EnsureSorted();
00219 
00220     PRInt32 i;
00221     PRInt32 result;
00222 
00223     // we ignore aStartTime
00224     for (i = 0; i < mDates.Count(); i++) {
00225         if (NS_SUCCEEDED(mDates[i]->Compare(aOccurrenceTime, &result)) && result > 0) {
00226             NS_ADDREF (*_retval = mDates[i]);
00227             return NS_OK;
00228         }
00229     }
00230 
00231     *_retval = nsnull;
00232     return NS_OK;
00233 }
00234 
00235 NS_IMETHODIMP
00236 calRecurrenceDateSet::GetOccurrences(calIDateTime *aStartTime,
00237                                      calIDateTime *aRangeStart,
00238                                      calIDateTime *aRangeEnd,
00239                                      PRUint32 aMaxCount,
00240                                      PRUint32 *aCount, calIDateTime ***aDates)
00241 {
00242     NS_ENSURE_ARG_POINTER(aStartTime);
00243     NS_ENSURE_ARG_POINTER(aRangeStart);
00244 
00245     nsCOMArray<calIDateTime> dates;
00246 
00247     PRInt32 i;
00248     PRInt32 result;
00249     nsresult rv;
00250 
00251     for (i = 0; i < mDates.Count(); i++) {
00252         rv = mDates[i]->Compare(aRangeStart, &result);
00253         NS_ENSURE_SUCCESS(rv, rv);
00254 
00255         // if the date is less than aRangeStart, continue
00256         if (result < 0)
00257             continue;
00258 
00259         // if the date is greater than aRangeEnd, break
00260         if (aRangeEnd) {
00261             rv = mDates[i]->Compare(aRangeEnd, &result);
00262             NS_ENSURE_SUCCESS(rv, rv);
00263             if (result >= 0)
00264                 break;
00265         }
00266 
00267         // append the date.
00268         dates.AppendObject(mDates[i]);
00269 
00270         // if we alrady have as many as we need, break.
00271         if (aMaxCount && dates.Count() == (int) aMaxCount)
00272             break;
00273     }
00274 
00275     PRInt32 count = dates.Count();
00276     if (count) {
00277         calIDateTime **dateArray = (calIDateTime **) nsMemory::Alloc(sizeof(calIDateTime*) * count);
00278         for (int i = 0; i < count; i++) {
00279             NS_ADDREF(dateArray[i] = dates[i]);
00280         }
00281         *aDates = dateArray;
00282     } else {
00283         *aDates = nsnull;
00284     }
00285     *aCount = count;
00286 
00287     return NS_OK;
00288 }
00289 
00293 NS_IMETHODIMP
00294 calRecurrenceDateSet::GetIcalProperty(calIIcalProperty **aProp)
00295 {
00296     icalproperty *dateset = nsnull;
00297 
00298     for (int i = 0; i < mDates.Count(); i++) {
00299         if (mIsNegative)
00300             dateset = icalproperty_new(ICAL_EXDATE_PROPERTY);
00301         else
00302             dateset = icalproperty_new(ICAL_RDATE_PROPERTY);
00303 
00304         struct icaltimetype icalt;
00305         mDates[i]->ToIcalTime(&icalt);
00306 
00307         icalvalue *v;
00308 
00309         if (icalt.is_date)
00310             v = icalvalue_new_date(icalt);
00311         else
00312             v = icalvalue_new_datetime(icalt);
00313 
00314         icalproperty_set_value(dateset, v);
00315     }
00316     
00317     return NS_ERROR_NOT_IMPLEMENTED;
00318 }
00319 
00320 NS_IMETHODIMP
00321 calRecurrenceDateSet::SetIcalProperty(calIIcalProperty *aProp)
00322 {
00323     return NS_ERROR_NOT_IMPLEMENTED;
00324 }