2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
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
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.
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
22 #include "iCalDataSource.h"
23 #include "iCalObject.h"
24 #include "iCalCalendar.h"
25 #include <SaxObjC/SaxObjC.h>
28 @interface NSObject(suppressCapitalizedKeyWarning)
29 + (void)suppressCapitalizedKeyWarning;
32 @implementation iCalDataSource
35 static id<NSObject,SaxXMLReader> parser = nil;
36 static SaxObjectDecoder *sax = nil;
38 - (void)_setupGlobals {
40 SaxXMLReaderFactory *factory =
41 [SaxXMLReaderFactory standardXMLReaderFactory];
42 parser = [[factory createXMLReaderForMimeType:@"text/calendar"] retain];
44 [self logWithFormat:@"ERROR: found no SAX driver for 'text/calendar'!"];
46 if (sax == nil && parser != nil) {
50 #if COCOA_Foundation_LIBRARY
51 /* otherwise we get warning on "X-WR-TIMEZONE" etc */
52 [NSClassFromString(@"NSKeyBinding") suppressCapitalizedKeyWarning];
55 bundle = [NSBundle bundleForClass:[self class]];
56 if ((p = [bundle pathForResource:@"NGiCal" ofType:@"xmap"]))
57 sax = [[SaxObjectDecoder alloc] initWithMappingAtPath:p];
59 sax = [[SaxObjectDecoder alloc] initWithMappingNamed:@"NGiCal"];
61 [parser setContentHandler:sax];
62 [parser setErrorHandler:sax];
67 - (id)initWithURL:(NSURL *)_url entityName:(NSString *)_ename {
69 if ((self = [super init])) {
70 self->url = [_url copy];
71 self->entityName = [_ename copy];
75 - (id)initWithPath:(NSString *)_path entityName:(NSString *)_ename {
78 lurl = [[[NSURL alloc] initFileURLWithPath:_path] autorelease];
79 return [self initWithURL:lurl entityName:_ename];
82 - (id)initWithURL:(NSURL *)_url {
83 return [self initWithURL:_url entityName:nil];
85 - (id)initWithPath:(NSString *)_path {
86 return [self initWithPath:_path entityName:nil];
89 return [self initWithURL:nil];
93 [self->fetchSpecification release];
94 [self->entityName release];
101 - (void)setFetchSpecification:(EOFetchSpecification *)_fspec {
102 if ([self->fetchSpecification isEqual:_fspec])
105 ASSIGNCOPY(self->fetchSpecification, _fspec);
107 [self postDataSourceChangedNotification];
109 - (EOFetchSpecification *)fetchSpecification {
110 return self->fetchSpecification;
115 - (id)_parseCalendar {
119 [self logWithFormat:@"ERROR: missing iCalendar parser!"];
123 [self logWithFormat:@"ERROR: missing SAX handler!"];
127 [parser parseFromSource:self->url];
128 cal = [sax rootObject];
133 - (NSArray *)objectsForEntityNamed:(NSString *)ename inCalendar:(id)_cal {
134 if ([ename isEqualToString:@"vevent"])
135 return [_cal events];
136 if ([ename isEqualToString:@"vtodo"])
138 if ([ename isEqualToString:@"vjournal"])
139 return [_cal journals];
140 if ([ename isEqualToString:@"vfreebusy"])
141 return [_cal freeBusys];
143 [self logWithFormat:@"unknown calendar entity '%@'", ename];
147 - (NSArray *)objectsFromCalendar:(id)_cal {
150 ename = [self->fetchSpecification entityName];
151 if ([ename length] == 0)
152 ename = self->entityName;
154 if ([ename length] == 0)
155 return [_cal allObjects];
157 if ([_cal isKindOfClass:[NSDictionary class]]) {
159 This happens with Mozilla Calendar which posts one vcalendar
160 entry (with method 'PUBLISH') per event.
166 if (![[_cal objectForKey:@"tag"] isEqualToString:@"iCalendar"]) {
168 @"ERROR: calendar (entity=%@) passed in as a dictionary: %@",
172 if ((calendars = [_cal objectForKey:@"subcomponents"]) == nil)
175 count = [calendars count];
176 ma = [NSMutableArray arrayWithCapacity:(count + 1)];
178 for (i = 0; i < count; i++) {
181 objects = [self objectsForEntityNamed:ename
182 inCalendar:[calendars objectAtIndex:i]];
183 if ([objects count] == 0)
186 [ma addObjectsFromArray:objects];
191 return [self objectsForEntityNamed:ename inCalendar:_cal];
194 - (NSArray *)fetchObjects {
195 NSAutoreleasePool *pool;
199 pool = [[NSAutoreleasePool alloc] init];
201 if ((calendar = [self _parseCalendar]) == nil)
204 if (self->fetchSpecification == nil) {
205 result = [[self objectsFromCalendar:calendar] shallowCopy];
217 objects = [self objectsFromCalendar:calendar];
219 /* first filter using qualifier */
221 ma = [NSMutableArray arrayWithCapacity:[objects count]];
222 q = [self->fetchSpecification qualifier];
223 e = [objects objectEnumerator];
224 while ((object = [e nextObject])) {
226 if (![(id<EOQualifierEvaluation>)q evaluateWithObject:object])
230 [ma addObject:object];
235 if ((sort = [self->fetchSpecification sortOrderings]))
236 [ma sortUsingKeyOrderArray:sort];
238 result = [ma shallowCopy];
243 return [result autorelease];
246 @end /* iCalDataSource */