]> err.no Git - scalable-opengroupware.org/blob - SOGoLogic/SOGoAppointment.m
fixes for SOGo bug #1070
[scalable-opengroupware.org] / SOGoLogic / SOGoAppointment.m
1 /*
2   Copyright (C) 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 // $Id$
22
23 #include "SOGoAppointment.h"
24 #include <SaxObjC/SaxObjC.h>
25 #include <NGiCal/NGiCal.h>
26 #include <EOControl/EOControl.h>
27 #include "SOGoAppointmentICalRenderer.h"
28 #include "common.h"
29
30 @interface SOGoAppointment (PrivateAPI)
31 - (NSArray *)_filteredAttendeesThinkingOfPersons:(BOOL)_persons;
32 @end
33
34 @implementation SOGoAppointment
35
36 static id<NSObject,SaxXMLReader> parser = nil;
37 static SaxObjectDecoder          *sax   = nil;
38
39 + (void)initialize {
40   if (parser == nil) {
41     parser = [[[SaxXMLReaderFactory standardXMLReaderFactory] 
42                 createXMLReaderForMimeType:@"text/calendar"]
43                 retain];
44     if (parser == nil)
45       NSLog(@"ERROR: did not find a parser for text/calendar!");
46   }
47   if (sax == nil) {
48     sax = [[SaxObjectDecoder alloc] initWithMappingNamed:@"NGiCal"];
49     if (sax == nil)
50       NSLog(@"ERROR: could not create the iCal SAX handler!");
51   }
52   
53   [parser setContentHandler:sax];
54   [parser setErrorHandler:sax];
55 }
56
57 - (id)initWithICalRootObject:(id)_root {
58   if ((self = [super init])) {
59 #if 0
60     [self logWithFormat:@"root is: %@", root];
61 #endif
62     
63     if ([_root isKindOfClass:[iCalEvent class]]) {
64       self->event = [_root retain];
65     }
66     else if ([_root isKindOfClass:[NSDictionary class]]) {
67       /* multiple vevents in the calendar */
68       [self errorWithFormat:
69               @"(%s): tried to initialize with multiple records: %@",
70               __PRETTY_FUNCTION__, _root];
71       [self release];
72       return nil;
73     }
74     else {
75       self->calendar = [_root retain];
76       self->event    = [[[self->calendar events] lastObject] retain];
77     }
78   }
79   return self;
80 }
81 - (id)initWithICalString:(NSString *)_iCal {
82   id root;
83   
84   if ([_iCal length] == 0) {
85     [self errorWithFormat:@"tried to init SOGoAppointment without iCal"];
86     [self release];
87     return nil;
88   }
89   if (parser == nil || sax == nil) {
90     [self errorWithFormat:@"iCal parser not properly set up!"];
91     [self release];
92     return nil;
93   }
94
95   if ([_iCal length] > 0) {
96     [parser parseFromSource:_iCal];
97     root = [[sax rootObject] retain]; /* retain to keep it around */
98     [sax reset];
99   }
100   else
101     root = nil;
102
103   self = [self initWithICalRootObject:root];
104   [root release];
105   return self;
106 }
107
108 - (void)dealloc {
109   [self->calendar release];
110   [self->event    release];
111   [super dealloc];
112 }
113
114 /* accessors */
115
116 - (id)calendar {
117   return self->calendar;
118 }
119
120 - (id)event {
121   return self->event;
122 }
123
124 - (NSString *)iCalString {
125   return [[SOGoAppointmentICalRenderer sharedAppointmentRenderer]
126                                        stringForAppointment:self];
127 }
128 - (NSString *)vEventString {
129   return [[SOGoAppointmentICalRenderer sharedAppointmentRenderer]
130                                        vEventStringForAppointment:self];
131 }
132
133 /* forwarded methods */
134
135 - (void)setUid:(NSString *)_value {
136   [self->event setUid:_value];
137 }
138 - (NSString *)uid {
139   return [self->event uid];
140 }
141
142 - (void)setSummary:(NSString *)_value {
143   [self->event setSummary:_value];
144 }
145 - (NSString *)summary {
146   return [self->event summary];
147 }
148
149 - (void)setLocation:(NSString *)_value {
150   [self->event setLocation:_value];
151 }
152 - (NSString *)location {
153   return [self->event location];
154 }
155 - (BOOL)hasLocation {
156   if (![[self location] isNotNull])
157     return NO;
158   return  [[self location] length] > 0 ? YES : NO;
159 }
160
161 - (void)setComment:(NSString *)_value {
162   if([_value length] == 0)
163     _value = nil;
164   [self->event setComment:_value];
165 }
166 - (NSString *)comment {
167   return [self->event comment];
168 }
169 - (BOOL)hasComment {
170   NSString *s = [self comment];
171   if(!s || [s length] == 0)
172     return NO;
173   return YES;
174 }
175
176 - (void)setPriority:(NSString *)_value {
177   [self->event setPriority:_value];
178 }
179 - (NSString *)priority {
180   return [self->event priority];
181 }
182 - (BOOL)hasPriority {
183   NSString *prio = [self priority];
184   NSRange r;
185   
186   if(!prio)
187     return NO;
188   
189   r = [prio rangeOfString:@";"];
190   if(r.length > 0) {
191     prio = [prio substringToIndex:r.location];
192   }
193   return [prio isEqualToString:@"0"] ? NO : YES;
194 }
195
196 - (void)setCategories:(NSArray *)_value {
197   NSString *catString;
198
199   if(!_value || [_value count] == 0) {
200     [self->event setCategories:nil];
201     return;
202   }
203   _value = [_value sortedArrayUsingSelector:@selector(compareAscending:)];
204   catString = [_value componentsJoinedByString:@","];
205   [self->event setCategories:catString];
206   [catString release];
207 }
208 - (NSArray *)categories {
209   NSString *catString;
210   NSArray *cats;
211   NSRange r;
212   
213   catString = [self->event categories];
214   if (![catString isNotNull])
215     return [NSArray array];
216   
217   r = [[catString stringValue] rangeOfString:@";"];
218   if(r.length > 0) {
219     catString = [catString substringToIndex:r.location];
220   }
221   cats = [catString componentsSeparatedByString:@","];
222   return cats;
223 }
224 - (BOOL)hasCategories {
225   return [self->event categories] != nil ? YES : NO;
226 }
227
228 - (void)setStatus:(NSString *)_value {
229   [self->event setStatus:_value];
230 }
231 - (NSString *)status {
232   return [self->event status];
233 }
234
235 - (void)setStartDate:(NSCalendarDate *)_date {
236   [self->event setStartDate:_date];
237 }
238 - (NSCalendarDate *)startDate {
239   return [self->event startDate];
240 }
241
242 - (void)setEndDate:(NSCalendarDate *)_date {
243   [self->event setEndDate:_date];
244 }
245 - (NSCalendarDate *)endDate {
246   return [self->event endDate];
247 }
248 - (BOOL)hasEndDate {
249   return [self->event hasEndDate];
250 }
251
252 - (void)setDuration:(NSTimeInterval)_duration {
253   // TODO
254   [self warnWithFormat:@"could not apply duration!"];
255 }
256 - (BOOL)hasDuration {
257   return [self->event hasDuration];
258 }
259 - (NSTimeInterval)duration {
260   return [self->event durationAsTimeInterval];
261 }
262
263 - (void)setOrganizer:(iCalPerson *)_organizer {
264   [self->event setOrganizer:_organizer];
265 }
266 - (iCalPerson *)organizer {
267   return [self->event organizer];
268 }
269
270 - (void)removeAllAttendees {
271   [self setAttendees:nil];
272 }
273 - (void)addToAttendees:(iCalPerson *)_person {
274   [self->event addToAttendees:_person];
275 }
276 - (void)appendAttendees:(NSArray *)_persons {
277   unsigned i, count;
278   
279   count = [_persons count];
280   for (i = 0; i < count; i++)
281     [self addToAttendees:[_persons objectAtIndex:i]];
282 }
283 - (void)setAttendees:(NSArray *)_persons {
284   [self->event removeAllAttendees];
285   if ([_persons count] > 0) 
286     [self appendAttendees:_persons];
287 }
288 - (NSArray *)attendees {
289   return [self->event attendees];
290 }
291
292 - (NSArray *)participants {
293   if (self->participants != nil)
294     return self->participants;
295   
296   self->participants = [[self _filteredAttendeesThinkingOfPersons:YES] retain];
297   return self->participants;
298 }
299 - (BOOL)hasParticipants {
300   return [[self participants] count] != 0;
301 }
302
303 - (NSArray *)resources {
304   return [self _filteredAttendeesThinkingOfPersons:NO];
305 }
306
307 - (NSArray *)_filteredAttendeesThinkingOfPersons:(BOOL)_persons {
308   NSArray        *list;
309   NSMutableArray *filtered;
310   unsigned       i, count;
311
312   list     = [self attendees];
313   count    = [list count];
314   filtered = [NSMutableArray arrayWithCapacity:count];
315   for (i = 0; i < count; i++) {
316     iCalPerson *p;
317     NSString   *role;
318     
319     p = [list objectAtIndex:i];
320     role = [p role];
321     if (_persons) {
322       if (role == nil || ![role hasPrefix:@"NON-PART"])
323         [filtered addObject:p];
324     }
325     else {
326       if ([role hasPrefix:@"NON-PART"])
327         [filtered addObject:p];
328     }
329   }
330   return filtered;
331 }
332
333 - (BOOL)isOrganizer:(id)_email {
334   return [[[self organizer] rfc822Email] isEqualToString:_email];
335 }
336
337 - (BOOL)isParticipant:(id)_email {
338   NSArray *partEmails;
339   
340   partEmails = [[self participants] valueForKey:@"rfc822Email"];
341   return [partEmails containsObject:_email];
342 }
343
344 /* description */
345
346 - (void)appendAttributesToDescription:(NSMutableString *)_ms {
347   [_ms appendFormat:@" uid=%@",  [self uid]];
348   [_ms appendFormat:@" date=%@", [self startDate]];
349 }
350
351 - (NSString *)description {
352   NSMutableString *ms;
353
354   ms = [NSMutableString stringWithCapacity:64];
355   [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
356   [self appendAttributesToDescription:ms];
357   [ms appendString:@">"];
358   return ms;
359 }
360
361 @end /* SOGoAppointment */