]> err.no Git - sope/blob - sope-ical/NGiCal/iCalEvent.m
recurrenceRule added to alarm, event, todo.
[sope] / sope-ical / NGiCal / iCalEvent.m
1 /*
2   Copyright (C) 2000-2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
6   OGo 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   OGo 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 OGo; 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 "iCalEvent.h"
23 #include "iCalPerson.h"
24 #include "iCalEventChanges.h"
25 #include "iCalRenderer.h"
26 #include "common.h"
27
28 @interface NSString(DurationTimeInterval)
29 - (NSTimeInterval)durationAsTimeInterval;
30 @end
31
32 @implementation iCalEvent
33
34 - (void)dealloc {
35   [self->duration       release];
36   [self->endDate        release];
37   [self->recurrenceRule release];
38   [super dealloc];
39 }
40
41 /* accessors */
42
43 - (void)setEndDate:(NSCalendarDate *)_date {
44   id tmp;
45   if (self->endDate == _date) return;
46   tmp = self->endDate;
47   self->endDate = [_date retain];
48   [tmp release];
49 }
50 - (NSCalendarDate *)endDate {
51   if ([self hasEndDate])
52     return self->endDate;
53   
54   if ([self hasDuration] && (self->startDate != nil)) {
55     return [[self startDate] dateByAddingYears:0 months:0 days:0
56                              hours:0 minutes:0 
57                              seconds:[self durationAsTimeInterval]];
58   }
59   return nil;
60 }
61 - (BOOL)hasEndDate {
62   return self->endDate ? YES : NO;
63 }
64
65 - (void)setTransp:(NSString *)_transp {
66   /* ignore transp ... (used by Evo 'TRANSP:OPAQUE') */
67 }
68
69 - (void)setDuration:(NSString *)_value {
70   ASSIGNCOPY(self->duration, _value);
71 }
72 - (NSString *)duration {
73   // eg: "DURATION:PT1H"
74   if ([self hasDuration])
75     return self->duration;
76   
77   // TODO: calculate
78   return nil;
79 }
80 - (BOOL)hasDuration {
81   return self->duration ? YES : NO;
82 }
83 - (NSTimeInterval)durationAsTimeInterval {
84   /*
85     eg: DURATION:PT1H
86     P      - "period"
87     P2H30M - "2 hours 30 minutes"
88
89      dur-value  = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
90
91      dur-date   = dur-day [dur-time]
92      dur-time   = "T" (dur-hour / dur-minute / dur-second)
93      dur-week   = 1*DIGIT "W"
94      dur-hour   = 1*DIGIT "H" [dur-minute]
95      dur-minute = 1*DIGIT "M" [dur-second]
96      dur-second = 1*DIGIT "S"
97      dur-day    = 1*DIGIT "D"
98   */
99   
100   if (self->duration)
101     return [self->duration durationAsTimeInterval];
102   
103   if (self->endDate != nil && self->startDate != nil)
104     /* calculate duration using enddate */
105     return [[self endDate] timeIntervalSinceDate:[self startDate]];
106   
107   return 0.0;
108 }
109
110 - (void)setRecurrenceRule:(NSString *)_recurrenceRule {
111   ASSIGN(self->recurrenceRule, _recurrenceRule);
112 }
113 - (NSString *)recurrenceRule {
114   return self->recurrenceRule;
115 }
116
117 /* ical typing */
118
119 - (NSString *)entityName {
120   return @"vevent";
121 }
122
123 /* descriptions */
124
125 - (NSString *)description {
126   NSMutableString *ms;
127
128   ms = [NSMutableString stringWithCapacity:128];
129   [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
130
131   if (self->uid)       [ms appendFormat:@" uid=%@", self->uid];
132   if (self->startDate) [ms appendFormat:@" from=%@", self->startDate];
133   if (self->endDate)   [ms appendFormat:@" to=%@", self->endDate];
134   if (self->summary)   [ms appendFormat:@" summary=%@", self->summary];
135   
136   if (self->organizer)
137     [ms appendFormat:@" organizer=%@", self->organizer];
138   if (self->attendees)
139     [ms appendFormat:@" attendees=%@", self->attendees];
140   
141   if ([self hasAlarms])
142     [ms appendFormat:@" alarms=%@", self->alarms];
143   
144   if (self->recurrenceRule)
145     [ms appendFormat:@" recurrenceRule=%@", self->recurrenceRule];
146
147   [ms appendString:@">"];
148   return ms;
149 }
150
151 /* changes */
152
153 - (iCalEventChanges *)getChangesRelativeToEvent:(iCalEvent *)_event {
154   return [iCalEventChanges changesFromEvent:_event
155                            toEvent:self];
156 }
157
158 /* generating iCal content */
159
160 - (NSString *)vEventString {
161   return [[iCalRenderer sharedICalendarRenderer] vEventStringForEvent:self];
162 }
163
164 @end /* iCalEvent */
165
166 @implementation NSString(DurationTimeInterval)
167
168 - (NSTimeInterval)durationAsTimeInterval {
169   /*
170     eg: DURATION:PT1H
171     P      - "period"
172     P2H30M - "2 hours 30 minutes"
173
174      dur-value  = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
175
176      dur-date   = dur-day [dur-time]
177      dur-time   = "T" (dur-hour / dur-minute / dur-second)
178      dur-week   = 1*DIGIT "W"
179      dur-hour   = 1*DIGIT "H" [dur-minute]
180      dur-minute = 1*DIGIT "M" [dur-second]
181      dur-second = 1*DIGIT "S"
182      dur-day    = 1*DIGIT "D"
183   */
184   unsigned       i, len;
185   NSTimeInterval ti;
186   BOOL           isTime;
187   int            val;
188     
189   if (![self hasPrefix:@"P"]) {
190     NSLog(@"Cannot parse iCal duration value: '%@'", self);
191     return 0.0;
192   }
193     
194   ti  = 0.0;
195   val = 0;
196   for (i = 1, len = [self length], isTime = NO; i < len; i++) {
197     unichar c;
198       
199     c = [self characterAtIndex:i];
200     if (c == 't' || c == 'T') {
201       isTime = YES;
202       val = 0;
203       continue;
204     }
205       
206     if (isdigit(c)) {
207       val = (val * 10) + (c - 48);
208       continue;
209     }
210       
211     switch (c) {
212     case 'W': /* week */
213       ti += (val * 7 * 24 * 60 * 60);
214       break;
215     case 'D': /* day  */
216       ti += (val * 24 * 60 * 60);
217       break;
218     case 'H': /* hour */
219       ti += (val * 60 * 60);
220       break;
221     case 'M': /* min  */
222       ti += (val * 60);
223       break;
224     case 'S': /* sec  */
225       ti += val;
226       break;
227     default:
228       [self logWithFormat:@"cannot process duration unit: '%c'", c];
229       break;
230     }
231     val = 0;
232   }
233   return ti;
234 }
235
236 @end /* NSString(DurationTimeInterval) */