]> err.no Git - sope/blob - sope-ical/NGiCal/iCalCalendar.m
use %p for pointer formats
[sope] / sope-ical / NGiCal / iCalCalendar.m
1 /*
2   Copyright (C) 2000-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 "iCalCalendar.h"
23 #include "iCalEvent.h"
24 #include "iCalToDo.h"
25 #include "iCalJournal.h"
26 #include "iCalFreeBusy.h"
27 #include "iCalEntityObject.h"
28 #include <SaxObjC/SaxObjC.h>
29 #include "common.h"
30
31 @interface iCalCalendar(Privates)
32 - (void)addToEvents:(iCalEvent *)_event;
33 - (void)addToTimezones:(id)_tz;
34 - (void)addToTodos:(iCalToDo *)_todo;
35 - (void)addToJournals:(iCalJournal *)_obj;
36 - (void)addToFreeBusys:(iCalFreeBusy *)_obj;
37 @end
38
39 @implementation iCalCalendar
40
41 static id<NSObject,SaxXMLReader> parser  = nil; // THREAD
42 static SaxObjectDecoder          *sax    = nil; // THREAD
43
44 + (int)version {
45   return [super version] + 0 /* v0 */;
46 }
47 + (void)initialize {
48   NSAssert2([super version] == 0,
49             @"invalid superclass (%@) version %i !",
50             NSStringFromClass([self superclass]), [super version]);
51 }
52
53 + (id<NSObject,SaxXMLReader>)iCalParser {
54   if (sax == nil) {
55     sax = [[SaxObjectDecoder alloc] initWithMappingNamed:@"NGiCal"];;
56     if (sax == nil) {
57       NSLog(@"ERROR(%s): could not create iCal SAX handler!",
58             __PRETTY_FUNCTION__);
59     }
60   }
61   if (sax != nil && parser == nil) {
62     parser =
63       [[[SaxXMLReaderFactory standardXMLReaderFactory] 
64                              createXMLReaderForMimeType:@"text/calendar"]
65                              retain];
66     if (parser == nil) {
67       NSLog(@"ERROR(%s): did not find a parser for text/calendar!",
68             __PRETTY_FUNCTION__);
69       return nil;
70     }
71     
72     [parser setContentHandler:sax];
73     [parser setErrorHandler:sax];
74   }
75   return parser;
76 }
77
78 + (iCalCalendar *)parseCalendarFromSource:(id)_src {
79   static id<NSObject,SaxXMLReader> parser;
80   id root, cal;
81   
82   if ((parser = [self iCalParser]) == nil)
83     return nil;
84   
85   [parser parseFromSource:_src];
86   root = [[sax rootObject] retain];
87   [sax reset];
88   
89   if (root == nil)
90     return nil;
91   if ([root isKindOfClass:self])
92     return [root autorelease];
93   
94   if (![root isKindOfClass:[iCalEntityObject class]]) {
95     NSLog(@"ERROR(%s): parsed object is of an unexpected class %@: %@",
96           __PRETTY_FUNCTION__, NSStringFromClass([root class]), root);
97     [root release];
98     return nil;
99   }
100   
101   /* so we just got an iCalEntityObject, wrap that manually into a cal */
102   cal = [[[self alloc] initWithEntityObject:root] autorelease];
103   [root release]; root = nil;
104   return cal;
105 }
106
107 - (id)initWithEntityObject:(iCalEntityObject *)_entityObject {
108   if ((self = [self init])) {
109     if ([_entityObject isKindOfClass:[iCalEvent class]])
110       [self addToEvents:(iCalEvent *)_entityObject];
111     else if ([_entityObject isKindOfClass:[iCalToDo class]])
112       [self addToTodos:(iCalToDo *)_entityObject];
113     else if ([_entityObject isKindOfClass:[iCalJournal class]])
114       [self addToJournals:(iCalJournal *)_entityObject];
115     else if ([_entityObject isKindOfClass:[iCalFreeBusy class]])
116       [self addToFreeBusys:(iCalFreeBusy *)_entityObject];
117     else if ([_entityObject isNotNull]) {
118       [self errorWithFormat:@"Unexpected entity object: %@", _entityObject];
119       [self release];
120       return nil;
121     }
122   }
123   return self;
124 }
125
126 - (void)dealloc {
127   [self->version   release];
128   [self->calscale  release];
129   [self->prodId    release];
130   [self->method    release];
131
132   [self->todos     release];
133   [self->events    release];
134   [self->journals  release];
135   [self->freeBusys release];
136   [self->timezones release];
137   [super dealloc];
138 }
139
140 /* NSCopying */
141
142 - (id)copyWithZone:(NSZone *)_zone {
143   iCalCalendar *new;
144   
145   new = [super copyWithZone:_zone];
146
147   new->version   = [self->version  copyWithZone:_zone];
148   new->calscale  = [self->calscale copyWithZone:_zone];
149   new->prodId    = [self->prodId   copyWithZone:_zone];
150   new->method    = [self->method   copyWithZone:_zone];
151
152   new->todos      = [self->todos     copyWithZone:_zone];
153   new->events     = [self->events    copyWithZone:_zone];
154   new->journals   = [self->journals  copyWithZone:_zone];
155   new->freeBusys  = [self->freeBusys copyWithZone:_zone];
156   new->timezones  = [self->timezones copyWithZone:_zone];
157
158   return new;
159 }
160
161 /* accessors */
162
163 - (void)setCalscale:(NSString *)_value {
164   ASSIGNCOPY(self->calscale, _value);
165 }
166 - (NSString *)calscale {
167   return self->calscale;
168 }
169 - (void)setVersion:(NSString *)_value {
170   ASSIGNCOPY(self->version, _value);
171 }
172 - (NSString *)version {
173   return self->version;
174 }
175 - (void)setProdId:(NSString *)_value {
176   ASSIGNCOPY(self->prodId, _value);
177 }
178 - (NSString *)prodId {
179   return self->prodId;
180 }
181 - (void)setMethod:(NSString *)_method {
182   ASSIGNCOPY(self->method, _method);
183 }
184 - (NSString *)method {
185   return self->method;
186 }
187
188 - (void)addToEvents:(iCalEvent *)_event {
189   if (_event == nil) return;
190   if (self->events == nil)
191     self->events = [[NSMutableArray alloc] initWithCapacity:4];
192   [self->events addObject:_event];
193 }
194 - (NSArray *)events {
195   return self->events;
196 }
197
198 - (void)addToTimezones:(id)_tz {
199   NSString *tzid;
200   
201   if (_tz == nil) return;
202   if (self->timezones == nil)
203     self->timezones = [[NSMutableDictionary alloc] initWithCapacity:4];
204   
205   if ((tzid = [_tz valueForKey:@"tzid"]) == nil) {
206     [self logWithFormat:@"ERROR: missing timezone-id in timezone: %@", _tz];
207     return;
208   }
209   [self->timezones setObject:_tz forKey:tzid];
210 }
211 - (NSArray *)timezones {
212   return [self->timezones allValues];
213 }
214
215 - (void)addToTodos:(iCalToDo *)_todo {
216   if (_todo == nil) return;
217   if (self->todos == nil)
218     self->todos = [[NSMutableArray alloc] initWithCapacity:4];
219   [self->todos addObject:_todo];
220 }
221 - (NSArray *)todos {
222   return self->todos;
223 }
224
225 - (void)addToJournals:(iCalJournal *)_obj {
226   if (_obj == nil) return;
227   if (self->journals == nil)
228     self->journals = [[NSMutableArray alloc] initWithCapacity:4];
229   [self->journals addObject:_obj];
230 }
231 - (NSArray *)journals {
232   return self->journals;
233 }
234
235 - (void)addToFreeBusys:(iCalFreeBusy *)_obj {
236   if (_obj == nil) return;
237   if (self->freeBusys == nil)
238     self->freeBusys = [[NSMutableArray alloc] initWithCapacity:4];
239   [self->freeBusys addObject:_obj];
240 }
241 - (NSArray *)freeBusys {
242   return self->freeBusys;
243 }
244
245 /* collection */
246
247 - (NSArray *)allObjects {
248   NSMutableArray *ma;
249   
250   ma = [NSMutableArray arrayWithCapacity:32];
251   if (self->events)    [ma addObjectsFromArray:self->events];
252   if (self->todos)     [ma addObjectsFromArray:self->todos];
253   if (self->freeBusys) [ma addObjectsFromArray:self->freeBusys];
254   if (self->journals)  [ma addObjectsFromArray:self->journals];
255   return ma;
256 }
257 - (NSEnumerator *)objectEnumerator {
258   return [[self allObjects] objectEnumerator];
259 }
260
261 /* ical typing */
262
263 - (NSString *)entityName {
264   return @"vcalendar";
265 }
266
267 /* descriptions */
268
269 - (NSString *)description {
270   NSMutableString *ms;
271
272   ms = [NSMutableString stringWithCapacity:128];
273   [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
274
275   if (self->version)  [ms appendFormat:@" v%@",         self->version];
276   if (self->method)   [ms appendFormat:@" method=%@",   self->method];
277   if (self->prodId)   [ms appendFormat:@" product=%@",  self->prodId];
278   if (self->calscale) [ms appendFormat:@" calscale=%@", self->calscale];
279
280   if ([self->events count] > 0)
281     [ms appendFormat:@" events=%@", self->events];
282   if ([self->todos count] > 0)
283     [ms appendFormat:@" todos=%@", self->todos];
284   if ([self->freeBusys count] > 0)
285     [ms appendFormat:@" fb=%@", self->freeBusys];
286   if ([self->journals count] > 0)
287     [ms appendFormat:@" journals=%@", self->journals];
288
289   if ([self->timezones count] > 0)
290     [ms appendFormat:@" tzs=%@", [self->timezones allKeys]];
291   
292   [ms appendString:@">"];
293   return ms;
294 }
295
296 @end /* iCalCalendar */