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