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];
95 [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 (![[(NSDictionary *)_cal objectForKey:@"tag"]
167 isEqualToString:@"iCalendar"]) {
169 @"ERROR: calendar (entity=%@) passed in as a dictionary: %@",
173 if ((calendars=[(NSDictionary *)_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 */