2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
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
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.
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
23 #include "iCalDataSource.h"
24 #include "iCalObject.h"
25 #include "iCalCalendar.h"
26 #include <SaxObjC/SaxObjC.h>
29 @interface NSObject(suppressCapitalizedKeyWarning)
30 + (void)suppressCapitalizedKeyWarning;
33 @implementation iCalDataSource
36 static id<NSObject,SaxXMLReader> parser = nil;
37 static SaxObjectDecoder *sax = nil;
39 - (void)_setupGlobals {
41 SaxXMLReaderFactory *factory =
42 [SaxXMLReaderFactory standardXMLReaderFactory];
43 parser = [[factory createXMLReaderForMimeType:@"text/calendar"] retain];
45 [self logWithFormat:@"ERROR: found no SAX driver for 'text/calendar'!"];
47 if (sax == nil && parser != nil) {
51 #if COCOA_Foundation_LIBRARY
52 /* otherwise we get warning on "X-WR-TIMEZONE" etc */
53 [NSClassFromString(@"NSKeyBinding") suppressCapitalizedKeyWarning];
56 bundle = [NSBundle bundleForClass:[self class]];
57 if ((p = [bundle pathForResource:@"NGiCal" ofType:@"xmap"]))
58 sax = [[SaxObjectDecoder alloc] initWithMappingAtPath:p];
60 sax = [[SaxObjectDecoder alloc] initWithMappingNamed:@"NGiCal"];
62 [parser setContentHandler:sax];
63 [parser setErrorHandler:sax];
68 - (id)initWithURL:(NSURL *)_url entityName:(NSString *)_ename {
70 if ((self = [super init])) {
71 self->url = [_url copy];
72 self->entityName = [_ename copy];
76 - (id)initWithPath:(NSString *)_path entityName:(NSString *)_ename {
79 lurl = [[[NSURL alloc] initFileURLWithPath:_path] autorelease];
80 return [self initWithURL:lurl entityName:_ename];
83 - (id)initWithURL:(NSURL *)_url {
84 return [self initWithURL:_url entityName:nil];
86 - (id)initWithPath:(NSString *)_path {
87 return [self initWithPath:_path entityName:nil];
90 return [self initWithURL:nil];
94 [self->fetchSpecification release];
95 [self->entityName release];
102 - (void)setFetchSpecification:(EOFetchSpecification *)_fspec {
103 if ([self->fetchSpecification isEqual:_fspec])
106 ASSIGNCOPY(self->fetchSpecification, _fspec);
108 [self postDataSourceChangedNotification];
110 - (EOFetchSpecification *)fetchSpecification {
111 return self->fetchSpecification;
116 - (id)_parseCalendar {
120 [self logWithFormat:@"ERROR: missing iCalendar parser!"];
124 [self logWithFormat:@"ERROR: missing SAX handler!"];
128 [parser parseFromSource:self->url];
129 cal = [sax rootObject];
134 - (NSArray *)objectsForEntityNamed:(NSString *)ename inCalendar:(id)_cal {
135 if ([ename isEqualToString:@"vevent"])
136 return [_cal events];
137 if ([ename isEqualToString:@"vtodo"])
139 if ([ename isEqualToString:@"vjournal"])
140 return [_cal journals];
141 if ([ename isEqualToString:@"vfreebusy"])
142 return [_cal freeBusys];
144 [self logWithFormat:@"unknown calendar entity '%@'", ename];
148 - (NSArray *)objectsFromCalendar:(id)_cal {
151 ename = [self->fetchSpecification entityName];
152 if ([ename length] == 0)
153 ename = self->entityName;
155 if ([ename length] == 0)
156 return [_cal allObjects];
158 if ([_cal isKindOfClass:[NSDictionary class]]) {
160 This happens with Mozilla Calendar which posts one vcalendar
161 entry (with method 'PUBLISH') per event.
167 if (![[_cal objectForKey:@"tag"] isEqualToString:@"iCalendar"]) {
169 @"ERROR: calendar (entity=%@) passed in as a dictionary: %@",
173 if ((calendars = [_cal objectForKey:@"subcomponents"]) == nil)
176 count = [calendars count];
177 ma = [NSMutableArray arrayWithCapacity:(count + 1)];
179 for (i = 0; i < count; i++) {
182 objects = [self objectsForEntityNamed:ename
183 inCalendar:[calendars objectAtIndex:i]];
184 if ([objects count] == 0)
187 [ma addObjectsFromArray:objects];
192 return [self objectsForEntityNamed:ename inCalendar:_cal];
195 - (NSArray *)fetchObjects {
196 NSAutoreleasePool *pool;
200 pool = [[NSAutoreleasePool alloc] init];
202 if ((calendar = [self _parseCalendar]) == nil)
205 if (self->fetchSpecification == nil) {
206 result = [[self objectsFromCalendar:calendar] shallowCopy];
218 objects = [self objectsFromCalendar:calendar];
220 /* first filter using qualifier */
222 ma = [NSMutableArray arrayWithCapacity:[objects count]];
223 q = [self->fetchSpecification qualifier];
224 e = [objects objectEnumerator];
225 while ((object = [e nextObject])) {
227 if (![(id<EOQualifierEvaluation>)q evaluateWithObject:object])
231 [ma addObject:object];
236 if ((sort = [self->fetchSpecification sortOrderings]))
237 [ma sortUsingKeyOrderArray:sort];
239 result = [ma shallowCopy];
244 return [result autorelease];
247 @end /* iCalDataSource */