2 Copyright (C) 2004-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with SOPE; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include "iCalRepeatableEntityObject.h"
23 #include <NGExtensions/NGCalendarDateRange.h>
24 #include "iCalRecurrenceRule.h"
25 #include "iCalRecurrenceCalculator.h"
28 @implementation iCalRepeatableEntityObject
31 [self->rRules release];
32 [self->exRules release];
33 [self->exDates release];
39 - (void)removeAllRecurrenceRules {
40 [self->rRules removeAllObjects];
42 - (void)addToRecurrenceRules:(id)_rrule {
43 if (_rrule == nil) return;
44 if (self->rRules == nil)
45 self->rRules = [[NSMutableArray alloc] initWithCapacity:1];
46 [self->rRules addObject:_rrule];
48 - (void)setRecurrenceRules:(NSArray *)_rrules {
49 if (_rrules == self->rRules)
51 [self->rRules release];
52 self->rRules = [_rrules mutableCopy];
54 - (BOOL)hasRecurrenceRules {
55 return [self->rRules count] > 0 ? YES : NO;
57 - (NSArray *)recurrenceRules {
61 - (void)removeAllExceptionRules {
62 [self->exRules removeAllObjects];
64 - (void)addToExceptionRules:(id)_rrule {
65 if (_rrule == nil) return;
66 if (self->exRules == nil)
67 self->exRules = [[NSMutableArray alloc] initWithCapacity:1];
68 [self->exRules addObject:_rrule];
70 - (void)setExceptionRules:(NSArray *)_rrules {
71 if (_rrules == self->exRules)
73 [self->exRules release];
74 self->exRules = [_rrules mutableCopy];
76 - (BOOL)hasExceptionRules {
77 return [self->exRules count] > 0 ? YES : NO;
79 - (NSArray *)exceptionRules {
83 - (void)removeAllExceptionDates {
84 [self->exDates removeAllObjects];
86 - (void)setExceptionDates:(NSArray *)_exDates {
87 if (_exDates == self->exDates)
89 [self->exDates release];
90 self->exDates = [_exDates mutableCopy];
92 - (void)addToExceptionDates:(id)_date {
93 if (_date == nil) return;
94 if (self->exDates == nil)
95 self->exDates = [[NSMutableArray alloc] initWithCapacity:4];
96 [self->exDates addObject:_date];
98 - (BOOL)hasExceptionDates {
99 return [self->exDates count] > 0 ? YES : NO;
101 - (NSArray *)exceptionDates {
102 return self->exDates;
107 - (BOOL)isRecurrent {
108 return [self hasRecurrenceRules] ? YES : NO;
113 - (BOOL)isWithinCalendarDateRange:(NGCalendarDateRange *)_range
114 firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir
118 ranges = [self recurrenceRangesWithinCalendarDateRange:_range
119 firstInstanceCalendarDateRange:_fir];
120 return [ranges count] > 0;
123 - (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r
124 firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir
126 iCalRecurrenceRule *rule;
127 iCalRecurrenceCalculator *calc;
128 NSMutableArray *ranges;
129 unsigned i, count, rCount;
131 ranges = [NSMutableArray array];
132 count = [self->rRules count];
133 for (i = 0; i < count; i++) {
136 rule = [self->rRules objectAtIndex:i];
137 calc = [iCalRecurrenceCalculator recurrenceCalculatorForRecurrenceRule:rule
138 withFirstInstanceCalendarDateRange:_fir];
139 rs = [calc recurrenceRangesWithinCalendarDateRange:_r];
140 [ranges addObjectsFromArray:rs];
146 /* test if any exceptions do match */
147 count = [self->exRules count];
148 for (i = 0; i < count; i++) {
151 rule = [self->exRules objectAtIndex:i];
152 calc = [iCalRecurrenceCalculator recurrenceCalculatorForRecurrenceRule:rule
153 withFirstInstanceCalendarDateRange:_fir];
154 rs = [calc recurrenceRangesWithinCalendarDateRange:_r];
155 [ranges removeObjectsInArray:rs];
161 /* exception dates are also possible */
162 rCount = [ranges count];
163 count = [self->exDates count];
164 for (i = 0; i < count; i++) {
165 NSCalendarDate *exDate;
166 NGCalendarDateRange *r;
169 exDate = [self->exDates objectAtIndex:i];
170 for (k = 0; k < rCount; k++) {
171 r = [ranges objectAtIndex:(rCount - k) - 1];
172 if ([r containsDate:exDate]) {
173 [ranges removeObjectAtIndex:k];
181 /* this is the outmost bound possible, not necessarily the real last date */
182 - (NSCalendarDate *)lastPossibleRecurrenceStartDateUsingFirstInstanceCalendarDateRange:(NGCalendarDateRange *)_r
184 NSCalendarDate *date;
187 count = [self->rRules count];
192 for (i = 0; i < count; i++) {
193 iCalRecurrenceRule *rule;
194 iCalRecurrenceCalculator *calc;
195 NSCalendarDate *rdate;
197 rule = [self->rRules objectAtIndex:i];
198 if ([rule isInfinite])
199 return nil; /* rule is not bound, hence no limit */
200 calc = [iCalRecurrenceCalculator recurrenceCalculatorForRecurrenceRule:rule
201 withFirstInstanceCalendarDateRange:_r];
202 rdate = [[calc lastInstanceCalendarDateRange] startDate];
203 if (date == nil || [date compare:rdate] == NSOrderedAscending)