From: helge Date: Sun, 15 Aug 2004 11:47:44 +0000 (+0000) Subject: git-svn-id: http://svn.opengroupware.org/SOGo/trunk@216 d1b88da0-ebda-0310-925b-ed51d... X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=22c15ffc56dba9984c82d52823404d631d114f58;p=scalable-opengroupware.org git-svn-id: http://svn.opengroupware.org/SOGo/trunk@216 d1b88da0-ebda-0310-925b-ed51d893ca5b --- diff --git a/SOGoLogic/ChangeLog b/SOGoLogic/ChangeLog index d59fe804..d1c81e2a 100644 --- a/SOGoLogic/ChangeLog +++ b/SOGoLogic/ChangeLog @@ -1,3 +1,11 @@ +2004-08-15 Helge Hess + + * v0.9.6 + + * added SOGoAppointmentICalRenderer + + * SOGoAppointment.m: some code cleanups + 2004-08-14 Marcus Mueller * UIxAppointmentEditor.m: changed filter. The iCalSaxDriver doesn't diff --git a/SOGoLogic/GNUmakefile b/SOGoLogic/GNUmakefile index 2696df68..cb125a08 100644 --- a/SOGoLogic/GNUmakefile +++ b/SOGoLogic/GNUmakefile @@ -9,13 +9,15 @@ libSOGoLogic_HEADER_FILES_DIR = . libSOGoLogic_HEADER_FILES_INSTALL_DIR = /SOGoLogic libSOGoLogic_SOVERSION=$(MAJOR_VERSION).$(MINOR_VERSION) -libSOGoLogic_HEADER_FILES += \ - SOGoAppointment.h \ - AgenorUserManager.h \ +libSOGoLogic_HEADER_FILES += \ + SOGoAppointment.h \ + SOGoAppointmentICalRenderer.h \ + AgenorUserManager.h -libSOGoLogic_OBJC_FILES += \ - SOGoAppointment.m \ - AgenorUserManager.m \ +libSOGoLogic_OBJC_FILES += \ + SOGoAppointment.m \ + SOGoAppointmentICalRenderer.m \ + AgenorUserManager.m -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/library.make diff --git a/SOGoLogic/SOGoAppointment.h b/SOGoLogic/SOGoAppointment.h index 1f72436a..b21ceba0 100644 --- a/SOGoLogic/SOGoAppointment.h +++ b/SOGoLogic/SOGoAppointment.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2004 SKYRIX Software AG + Copyright (C) 2004 SKYRIX Software AG This file is part of OpenGroupware.org. @@ -20,21 +20,27 @@ */ // $Id$ - #ifndef __SOGoAppointment_H_ #define __SOGoAppointment_H_ +#import +#import -#import +/* + SOGoAppointment + + Wrapper around the iCalendar content of appointments stored in the + OGoContentStore. +*/ +@class NSString, NSArray; @class iCalPerson; - @interface SOGoAppointment : NSObject { - id calendar; - id event; - id participants; + id calendar; + id event; + id participants; } - (id)initWithICalString:(NSString *)_iCal; @@ -76,10 +82,12 @@ /* attendees -> role == X-OGo-RESOURCE */ - (NSArray *)resources; -/* TODO: should have coder instead */ +/* iCal generation */ + - (NSString *)iCalString; -/* do we really need these? */ +/* raw entity objects */ + - (id)calendar; - (id)event; diff --git a/SOGoLogic/SOGoAppointment.m b/SOGoLogic/SOGoAppointment.m index d176dd1b..6fda9625 100644 --- a/SOGoLogic/SOGoAppointment.m +++ b/SOGoLogic/SOGoAppointment.m @@ -20,17 +20,13 @@ */ // $Id$ - #include "SOGoAppointment.h" +#include "SOGoAppointmentICalRenderer.h" #include #include #include #include "common.h" -@interface NSDate(UsedPrivates) -- (NSString *)icalString; // declared in NGiCal -@end - @interface SOGoAppointment (PrivateAPI) - (NSArray *)_filteredAttendeesThinkingOfPersons:(BOOL)_persons; @end @@ -58,52 +54,56 @@ static SaxObjectDecoder *sax = nil; [parser setErrorHandler:sax]; } -- (id)initWithICalString:(NSString *)_iCal { - if ([_iCal length] == 0) { - [self logWithFormat:@"ERROR: tried to init SOGoAppointment without iCal"]; - [self release]; - return nil; - } - if ((self = [self init])) { - id root; +- (id)initWithICalRootObject:(id)_root { + if ((self = [super init])) { +#if 0 + [self logWithFormat:@"root is: %@", root]; +#endif - if (parser == nil || sax == nil) { - [self release]; - return nil; + if ([_root isKindOfClass:[iCalEvent class]]) { + self->event = [_root retain]; } - - /* parse */ - - if ([_iCal length] > 0) { - [parser parseFromSource:_iCal]; - root = [[sax rootObject] retain]; - [sax reset]; - } - else - root = nil; - - /* fill */ - - // [self logWithFormat:@"root is: %@", root]; - - if ([root isKindOfClass:[iCalEvent class]]) { - self->event = root; - } - else if ([root isKindOfClass:[NSDictionary class]]) { + else if ([_root isKindOfClass:[NSDictionary class]]) { /* multiple vevents in the calendar */ [self logWithFormat: @"ERROR(%s): tried to initialize with multiple records: %@", - __PRETTY_FUNCTION__, root]; + __PRETTY_FUNCTION__, _root]; [self release]; return nil; } else { - self->calendar = root; + self->calendar = [_root retain]; self->event = [[[self->calendar events] lastObject] retain]; } } return self; } +- (id)initWithICalString:(NSString *)_iCal { + id root; + + if ([_iCal length] == 0) { + [self logWithFormat:@"ERROR: tried to init SOGoAppointment without iCal"]; + [self release]; + return nil; + } + if (parser == nil || sax == nil) { + [self logWithFormat:@"ERROR: iCal parser not properly set up!"]; + [self release]; + return nil; + } + + if ([_iCal length] > 0) { + [parser parseFromSource:_iCal]; + root = [[sax rootObject] retain]; /* retain to keep it around */ + [sax reset]; + } + else + root = nil; + + self = [self initWithICalRootObject:root]; + [root release]; + return self; +} - (void)dealloc { [self->calendar release]; @@ -121,101 +121,13 @@ static SaxObjectDecoder *sax = nil; return self->event; } -/* TODO: REMOVE THIS HACK ASAP */ - (NSString *)iCalString { - NSMutableString *s; - NSArray *persons; - unsigned i, count; - iCalPerson *p; - - /* assume length of 1K - reasonable ? */ - s = [NSMutableString stringWithCapacity:1024]; - - [s appendString:@"BEGIN:VCALENDAR\nMETHOD:REQUEST\nPRODID:"]; - if (self->calendar == nil) - [s appendString:@"SOGo/0.9"]; - else - [s appendString:[self->calendar prodId]]; - [s appendString:@"\nVERSION:"]; - if (self->calendar == nil) - [s appendString:@"2.0"]; - else - [s appendString:[(iCalCalendar *)self->calendar version]]; - [s appendString:@"\nBEGIN:VEVENT"]; - [s appendString:@"\nSUMMARY:"]; - [s appendString:[self summary]]; - if([self hasLocation]) { - [s appendString:@"\nLOCATION:"]; - [s appendString:[self location]]; - } - [s appendString:@"\nUID:"]; - [s appendString:[self uid]]; - [s appendString:@"\nDTSTART:"]; - [s appendString:[[self startDate] icalString]]; - if([self hasEndDate]) { - [s appendString:@"\nDTEND:"]; - [s appendString:[[self endDate] icalString]]; - } - if([self hasDuration]) { - [s appendString:@"\nDURATION:"]; - [s appendString:[(iCalEvent *)self->event duration]]; - } - [s appendString:@"\nSTATUS:"]; - [s appendString:[self status]]; - - /* what's all this? */ - [s appendString:@"\nTRANSP:OPAQUE"]; /* transparency */ - [s appendString:@"\nCLASS:PRIVATE"]; /* classification [like 'top secret'] */ - - /* organizer */ - p = [self organizer]; - if(p) { - NSString *x; - - [s appendString:@"\nORGANIZER;CN=\""]; - if((x = [p cn])) { - [s appendString:x]; - } - [s appendString:@"\""]; - if((x = [p email])) { - [s appendString:@":"]; /* sic! */ - [s appendString:x]; - } - } - - /* attendees */ - persons = [self attendees]; - count = [persons count]; - for (i = 0; i < count; i++) { - NSString *x; - - p = [persons objectAtIndex:i]; - [s appendString:@"\nATTENDEE;"]; - if((x = [p role])) { - [s appendString:@"ROLE="]; - [s appendString:x]; - [s appendString:@";"]; - } - [s appendString:@"CN=\""]; - if((x = [p cn])) { - [s appendString:x]; - } - [s appendString:@"\""]; - if((x = [p email])) { - [s appendString:@":"]; /* sic! */ - [s appendString:x]; - } - } - - /* postamble */ - [s appendString:@"\nEND:VEVENT\nEND:VCALENDAR"]; - return s; + return [[SOGoAppointmentICalRenderer sharedAppointmentRenderer] + stringForAppointment:self]; } - /* forwarded methods */ - - (void)setUid:(NSString *)_value { [self->event setUid:_value]; } @@ -231,114 +143,115 @@ static SaxObjectDecoder *sax = nil; } - (void)setLocation:(NSString *)_value { - [self->event setLocation:_value]; + [self->event setLocation:_value]; } - (NSString *)location { - return [self->event location]; + return [self->event location]; } - (BOOL)hasLocation { - return ([self location] != nil) && ([[self location] length] > 0); + if (![[self location] isNotNull]) + return NO; + return [[self location] length] > 0 ? YES : NO; } - (void)setStatus:(NSString *)_value { - [self->event setStatus:_value]; + [self->event setStatus:_value]; } - (NSString *)status { - return [(iCalEvent *)self->event status]; + return [(iCalEvent *)self->event status]; } - (void)setStartDate:(NSCalendarDate *)_date { - [self->event setStartDate:_date]; + [self->event setStartDate:_date]; } - - (NSCalendarDate *)startDate { - return [self->event startDate]; + return [self->event startDate]; } - (void)setEndDate:(NSCalendarDate *)_date { - [self->event setEndDate:_date]; + [self->event setEndDate:_date]; } - (NSCalendarDate *)endDate { - return [self->event endDate]; + return [self->event endDate]; } - (BOOL)hasEndDate { - return [self->event hasEndDate]; + return [self->event hasEndDate]; } -- (BOOL)hasDuration { - return [self->event hasDuration]; -} - (void)setDuration:(NSTimeInterval)_duration { + // TODO + [self logWithFormat:@"WARNING: could not apply duration!"]; +} +- (BOOL)hasDuration { + return [self->event hasDuration]; } - (NSTimeInterval)duration { - return [self->event durationAsTimeInterval]; + return [self->event durationAsTimeInterval]; } - (void)setOrganizer:(iCalPerson *)_organizer { - [self->event setOrganizer:_organizer]; + [self->event setOrganizer:_organizer]; } - (iCalPerson *)organizer { - return [self->event organizer]; + return [self->event organizer]; } - (void)removeAllAttendees { - [self->event removeAllAttendees]; + [self->event removeAllAttendees]; } - (void)addToAttendees:(iCalPerson *)_person { - [self->event addToAttendees:_person]; + [self->event addToAttendees:_person]; } - (void)appendAttendees:(NSArray *)_persons { - unsigned i, count; - - count = [_persons count]; - for(i = 0; i < count; i++) { - [self addToAttendees:[_persons objectAtIndex:i]]; - } + unsigned i, count; + + count = [_persons count]; + for (i = 0; i < count; i++) + [self addToAttendees:[_persons objectAtIndex:i]]; } - (NSArray *)attendees { - return [self->event attendees]; -} - -- (BOOL)hasParticipants { - return [[self participants] count] != 0; + return [self->event attendees]; } - (NSArray *)participants { - if(self->participants == nil) { - ASSIGN(self->participants, - [self _filteredAttendeesThinkingOfPersons:YES]); - } + if (self->participants) return self->participants; + + self->participants = [[self _filteredAttendeesThinkingOfPersons:YES] retain]; + return self->participants; +} +- (BOOL)hasParticipants { + return [[self participants] count] != 0; } - (NSArray *)resources { - return [self _filteredAttendeesThinkingOfPersons:NO]; + return [self _filteredAttendeesThinkingOfPersons:NO]; } - (NSArray *)_filteredAttendeesThinkingOfPersons:(BOOL)_persons { - NSArray *list; - NSMutableArray *filtered; - unsigned i, count; - - list = [self attendees]; - count = [list count]; - filtered = [[NSMutableArray alloc] initWithCapacity:count]; - for(i = 0; i < count; i++) { - iCalPerson *p; - NSString *role; - - p = [list objectAtIndex:i]; - role = [p role]; - if(_persons) { - if(role == nil || ![role isEqualToString:@"NON-PART"]) - [filtered addObject:p]; - } - else { - if([role isEqualToString:@"NON-PART"]) - [filtered addObject:p]; - } + NSArray *list; + NSMutableArray *filtered; + unsigned i, count; + + list = [self attendees]; + count = [list count]; + filtered = [NSMutableArray arrayWithCapacity:count]; + for (i = 0; i < count; i++) { + iCalPerson *p; + NSString *role; + + p = [list objectAtIndex:i]; + role = [p role]; + if (_persons) { + if (role == nil || ![role isEqualToString:@"NON-PART"]) + [filtered addObject:p]; } - return [filtered autorelease]; + else { + if ([role isEqualToString:@"NON-PART"]) + [filtered addObject:p]; + } + } + return filtered; } -@end +@end /* SOGoAppointment */ diff --git a/SOGoLogic/SOGoAppointmentICalRenderer.h b/SOGoLogic/SOGoAppointmentICalRenderer.h new file mode 100644 index 00000000..3eebed2d --- /dev/null +++ b/SOGoLogic/SOGoAppointmentICalRenderer.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2004 SKYRIX Software AG + + This file is part of OpenGroupware.org. + + OGo is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + OGo is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with OGo; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ +// $Id: SOGoAppointment.h 207 2004-08-14 15:37:04Z znek $ + +#ifndef __SOGoAppointmentICalRenderer_H_ +#define __SOGoAppointmentICalRenderer_H_ + +#import + +/* + SOGoAppointmentICalRenderer + + Transform an SOGoAppointment into an iCalendar formatted string. +*/ + +@class NSString; +@class SOGoAppointment; + +@interface SOGoAppointmentICalRenderer : NSObject + ++ (id)sharedAppointmentRenderer; + +- (NSString *)stringForAppointment:(SOGoAppointment *)_apt; + +@end + +#endif /* __SOGoAppointmentICalRenderer_H_ */ diff --git a/SOGoLogic/SOGoAppointmentICalRenderer.m b/SOGoLogic/SOGoAppointmentICalRenderer.m new file mode 100644 index 00000000..ec1d035b --- /dev/null +++ b/SOGoLogic/SOGoAppointmentICalRenderer.m @@ -0,0 +1,176 @@ +/* + Copyright (C) 2004 SKYRIX Software AG + + This file is part of OpenGroupware.org. + + OGo is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + OGo is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with OGo; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ + +#include "SOGoAppointmentICalRenderer.h" +#include "SOGoAppointment.h" +#include +#include "common.h" + +// TODO: the basic renderer should be part of NGiCal + +@interface NSDate(UsedPrivates) +- (NSString *)icalString; // declared in NGiCal +@end + +@implementation SOGoAppointmentICalRenderer + +static SOGoAppointmentICalRenderer *renderer = nil; + ++ (id)sharedAppointmentRenderer { + if (renderer == nil) + renderer = [[self alloc] init]; + return renderer; +} + +/* renderer */ + +- (void)addPreambleForAppointment:(SOGoAppointment *)_apt + toString:(NSMutableString *)s +{ + iCalCalendar *calendar; + + calendar = [_apt calendar]; + + [s appendString:@"BEGIN:VCALENDAR\nMETHOD:REQUEST\n"]; + + [s appendString:@"PRODID:"]; + [s appendString:[calendar isNotNull] ? [calendar prodId] : @"SOGo/0.9"]; + [s appendString:@"\n"]; + + [s appendString:@"\nVERSION:"]; + [s appendString:[calendar isNotNull] ? [calendar version] : @"2.0"]; + [s appendString:@"\n"]; +} +- (void)addPostambleForAppointment:(SOGoAppointment *)_apt + toString:(NSMutableString *)s +{ + [s appendString:@"END:VCALENDAR\n"]; +} + +- (void)addOrganizer:(iCalPerson *)p toString:(NSMutableString *)s { + NSString *x; + + if (![p isNotNull]) return; + + [s appendString:@"ORGANIZER;CN=\""]; + if ((x = [p cn])) + [s appendString:x]; + + [s appendString:@"\""]; + if ((x = [p email])) { + [s appendString:@":"]; /* sic! */ + [s appendString:x]; + } + [s appendString:@"\n"]; +} + +- (void)addAttendees:(NSArray *)persons toString:(NSMutableString *)s { + unsigned i, count; + iCalPerson *p; + + count = [persons count]; + for (i = 0; i < count; i++) { + NSString *x; + + p = [persons objectAtIndex:i]; + [s appendString:@"ATTENDEE;"]; + + if ((x = [p role])) { + [s appendString:@"ROLE="]; + [s appendString:x]; + [s appendString:@";"]; + } + + [s appendString:@"CN=\""]; + if ((x = [p cn])) { + [s appendString:x]; + } + [s appendString:@"\""]; + if ([(x = [p email]) isNotNull]) { + [s appendString:@":"]; /* sic! */ + [s appendString:x]; + } + [s appendString:@"\n"]; + } +} + +- (void)addVEventForAppointment:(SOGoAppointment *)_apt + toString:(NSMutableString *)s +{ + iCalEvent *event; + + event = [_apt event]; + + [s appendString:@"BEGIN:VEVENT\n"]; + + [s appendString:@"SUMMARY:"]; + [s appendString:[_apt summary]]; + [s appendString:@"\n"]; + if ([_apt hasLocation]) { + [s appendString:@"LOCATION:"]; + [s appendString:[_apt location]]; + [s appendString:@"\n"]; + } + [s appendString:@"UID:"]; + [s appendString:[_apt uid]]; + [s appendString:@"\n"]; + + [s appendString:@"DTSTART:"]; + [s appendString:[[_apt startDate] icalString]]; + [s appendString:@"\n"]; + if ([_apt hasEndDate]) { + [s appendString:@"DTEND:"]; + [s appendString:[[_apt endDate] icalString]]; + } + if ([_apt hasDuration]) { + [s appendString:@"DURATION:"]; + [s appendString:[event duration]]; + } + [s appendString:@"\n"]; + + [s appendString:@"STATUS:"]; + [s appendString:[_apt status]]; + [s appendString:@"\n"]; + + /* what's all this? */ + [s appendString:@"TRANSP:OPAQUE"]; /* transparency */ + [s appendString:@"\nCLASS:PRIVATE"]; /* classification [like 'top secret'] */ + [s appendString:@"\n"]; + + [self addOrganizer:[_apt organizer] toString:s]; + [self addAttendees:[_apt attendees] toString:s]; + + /* postamble */ + [s appendString:@"END:VEVENT\n"]; +} + +- (NSString *)stringForAppointment:(SOGoAppointment *)_apt { + NSMutableString *s; + + /* assume length of 1K - reasonable ? */ + s = [NSMutableString stringWithCapacity:1024]; + [self addPreambleForAppointment:_apt toString:s]; + [self addVEventForAppointment:_apt toString:s]; + [self addPostambleForAppointment:_apt toString:s]; + return s; +} + +@end /* SOGoAppointmentICalRenderer */ diff --git a/SOGoLogic/Version b/SOGoLogic/Version index 6b227f7e..0eb47da3 100644 --- a/SOGoLogic/Version +++ b/SOGoLogic/Version @@ -1,3 +1,3 @@ # $Id$ -SUBMINOR_VERSION:=5 +SUBMINOR_VERSION:=6