]> err.no Git - sope/blob - sope-ical/NGiCal/iCalRepeatableEntityObject.m
b04f28149341c0e17b2513a1f442200e12aca65f
[sope] / sope-ical / NGiCal / iCalRepeatableEntityObject.m
1 /*
2   Copyright (C) 2004-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21
22 #include "iCalRepeatableEntityObject.h"
23 #include <NGExtensions/NGCalendarDateRange.h>
24 #include "iCalRecurrenceRule.h"
25 #include "iCalRecurrenceCalculator.h"
26 #include "common.h"
27
28 @implementation iCalRepeatableEntityObject
29
30 + (int)version {
31   return [super version] + 0 /* v0 */;
32 }
33 + (void)initialize {
34   NSAssert2([super version] == 0,
35             @"invalid superclass (%@) version %i !",
36             NSStringFromClass([self superclass]), [super version]);
37 }
38
39 - (void)dealloc {
40   [self->rRules  release];
41   [self->exRules release];
42   [self->exDates release];
43   [super dealloc];
44 }
45
46 /* NSCopying */
47
48 - (id)copyWithZone:(NSZone *)_zone {
49   iCalRepeatableEntityObject *new;
50
51   new = [super copyWithZone:_zone];
52   
53   new->rRules  = [self->rRules  copyWithZone:_zone];
54   new->exRules = [self->exRules copyWithZone:_zone];
55   new->exDates = [self->exDates copyWithZone:_zone];
56
57   return new;
58 }
59
60 /* Accessors */
61
62 - (void)removeAllRecurrenceRules {
63   [self->rRules removeAllObjects];
64 }
65 - (void)addToRecurrenceRules:(id)_rrule {
66   if (_rrule == nil) return;
67   if (self->rRules == nil)
68     self->rRules = [[NSMutableArray alloc] initWithCapacity:1];
69   [self->rRules addObject:_rrule];
70 }
71 - (void)setRecurrenceRules:(NSArray *)_rrules {
72   if (_rrules == self->rRules)
73     return;
74   [self->rRules release];
75   self->rRules = [_rrules mutableCopy];
76 }
77 - (BOOL)hasRecurrenceRules {
78   return [self->rRules count] > 0 ? YES : NO;
79 }
80 - (NSArray *)recurrenceRules {
81   return self->rRules;
82 }
83
84 - (void)removeAllExceptionRules {
85   [self->exRules removeAllObjects];
86 }
87 - (void)addToExceptionRules:(id)_rrule {
88   if (_rrule == nil) return;
89   if (self->exRules == nil)
90     self->exRules = [[NSMutableArray alloc] initWithCapacity:1];
91   [self->exRules addObject:_rrule];
92 }
93 - (void)setExceptionRules:(NSArray *)_rrules {
94   if (_rrules == self->exRules)
95     return;
96   [self->exRules release];
97   self->exRules = [_rrules mutableCopy];
98 }
99 - (BOOL)hasExceptionRules {
100   return [self->exRules count] > 0 ? YES : NO;
101 }
102 - (NSArray *)exceptionRules {
103   return self->exRules;
104 }
105
106 - (void)removeAllExceptionDates {
107   [self->exDates removeAllObjects];
108 }
109 - (void)setExceptionDates:(NSArray *)_exDates {
110   if (_exDates == self->exDates)
111     return;
112   [self->exDates release];
113   self->exDates = [_exDates mutableCopy];
114 }
115 - (void)addToExceptionDates:(id)_date {
116   if (_date == nil) return;
117   if (self->exDates == nil)
118     self->exDates = [[NSMutableArray alloc] initWithCapacity:4];
119   [self->exDates addObject:_date];
120 }
121 - (BOOL)hasExceptionDates {
122   return [self->exDates count] > 0 ? YES : NO;
123 }
124 - (NSArray *)exceptionDates {
125   return self->exDates;
126 }
127
128 /* Convenience */
129
130 - (BOOL)isRecurrent {
131   return [self hasRecurrenceRules] ? YES : NO;
132 }
133
134 /* Matching */
135
136 - (BOOL)isWithinCalendarDateRange:(NGCalendarDateRange *)_range
137   firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir
138 {
139   NSArray *ranges;
140   
141   ranges = [self recurrenceRangesWithinCalendarDateRange:_range
142                  firstInstanceCalendarDateRange:_fir];
143   return [ranges count] > 0;
144 }
145
146 - (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r
147   firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir
148 {
149   return [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange:_r
150                                    firstInstanceCalendarDateRange:_fir
151                                    recurrenceRules:self->rRules
152                                    exceptionRules:self->exRules
153                                    exceptionDates:self->exDates];
154 }
155
156
157 /* this is the outmost bound possible, not necessarily the real last date */
158 - (NSCalendarDate *)lastPossibleRecurrenceStartDateUsingFirstInstanceCalendarDateRange:(NGCalendarDateRange *)_r
159 {
160   NSCalendarDate *date;
161   unsigned       i, count;
162   
163   count = [self->rRules count];
164   if (!count)
165     return nil;
166
167   date  = nil;
168   for (i = 0; i < count; i++) {
169     iCalRecurrenceRule       *rule;
170     iCalRecurrenceCalculator *calc;
171     NSCalendarDate           *rdate;
172
173     rule = [self->rRules objectAtIndex:i];
174     if ([rule isInfinite])
175       return nil; /* rule is not bound, hence no limit */
176     calc  = [iCalRecurrenceCalculator recurrenceCalculatorForRecurrenceRule:rule
177                                       withFirstInstanceCalendarDateRange:_r];
178     rdate = [[calc lastInstanceCalendarDateRange] startDate];
179     if (date == nil || [date compare:rdate] == NSOrderedAscending)
180       date = rdate;
181   }
182   return date;
183 }
184
185 @end