From 5d47bd1d68f19ae965a5c54288cae3c755e3d68d Mon Sep 17 00:00:00 2001 From: helge Date: Tue, 19 Oct 2004 16:52:05 +0000 Subject: [PATCH] work on iCal file fetch git-svn-id: http://svn.opengroupware.org/SOGo/trunk@409 d1b88da0-ebda-0310-925b-ed51d893ca5b --- OGoContentStore/ChangeLog | 7 +++ OGoContentStore/OCSFolder.h | 3 + OGoContentStore/OCSFolder.m | 60 +++++++++++++++++++ OGoContentStore/Version | 2 +- SOGo/Protocols/iCalHTTP/ChangeLog | 3 +- SOGo/Protocols/iCalHTTP/GNUmakefile | 1 + SOGo/Protocols/iCalHTTP/SOGoICalFileFetch.m | 51 ++++++++++++++++ SOGo/Protocols/iCalHTTP/SOGoICalHTTPHandler.h | 4 ++ SOGo/Protocols/iCalHTTP/SOGoICalHTTPHandler.m | 29 ++++----- SOGo/Protocols/iCalHTTP/Version | 2 +- SOGo/Protocols/iCalHTTP/product.plist | 5 +- SOGo/SoObjects/Appointments/ChangeLog | 8 +++ .../Appointments/SOGoAppointmentFolder.h | 4 ++ .../Appointments/SOGoAppointmentFolder.m | 42 +++++++++++++ SOGo/SoObjects/Appointments/Version | 4 +- SOGo/SoObjects/SOGo/ChangeLog | 7 +++ SOGo/SoObjects/SOGo/SOGoFolder.h | 13 ++++ SOGo/SoObjects/SOGo/SOGoFolder.m | 14 ++++- SOGo/SoObjects/SOGo/Version | 4 +- SOGoLogic/ChangeLog | 4 ++ SOGoLogic/SOGoAppointment.h | 4 +- SOGoLogic/SOGoAppointment.m | 17 ++++++ SOGoLogic/Version | 2 +- 23 files changed, 259 insertions(+), 31 deletions(-) create mode 100644 SOGo/Protocols/iCalHTTP/SOGoICalFileFetch.m diff --git a/OGoContentStore/ChangeLog b/OGoContentStore/ChangeLog index 57eda4a1..0d53641f 100644 --- a/OGoContentStore/ChangeLog +++ b/OGoContentStore/ChangeLog @@ -1,3 +1,10 @@ +2004-10-19 Helge Hess + + * OCSFolder.m: added new method -fetchContentsOfAllFiles method which + fetches the contents of all files stored in the folder (required for + iCal generation, such bulk fetches should be avoided if possible!) + (v0.9.13) + 2004-10-15 Marcus Mueller * OCSStringFormatter.[hm]: minor cleanup (v0.9.12) diff --git a/OGoContentStore/OCSFolder.h b/OGoContentStore/OCSFolder.h index 267de0ea..89000bad 100644 --- a/OGoContentStore/OCSFolder.h +++ b/OGoContentStore/OCSFolder.h @@ -26,6 +26,7 @@ #import @class NSString, NSURL, NSNumber, NSArray, NSException, NSMutableString; +@class NSDictionary; @class EOQualifier, EOFetchSpecification; @class EOAdaptorChannel; @class OCSFolderManager, OCSFolderType, OCSChannelManager; @@ -81,6 +82,8 @@ - (NSException *)writeContent:(NSString *)_content toName:(NSString *)_name; - (NSException *)deleteContentWithName:(NSString *)_name; +- (NSDictionary *)fetchContentsOfAllFiles; + - (NSArray *)fetchFields:(NSArray *)_flds fetchSpecification:(EOFetchSpecification *)_fs; - (NSArray *)fetchFields:(NSArray *)_flds matchingQualifier:(EOQualifier *)_q; diff --git a/OGoContentStore/OCSFolder.m b/OGoContentStore/OCSFolder.m index adedbf24..b0f92c94 100644 --- a/OGoContentStore/OCSFolder.m +++ b/OGoContentStore/OCSFolder.m @@ -223,6 +223,66 @@ static OCSStringFormatter *stringFormatter = nil; inContentWithName:_name]; } +- (NSDictionary *)fetchContentsOfAllFiles { + /* + Note: try to avoid the use of this method! The key of the dictionary + will be filename, the value the content. + */ + NSMutableDictionary *result; + EOAdaptorChannel *channel; + NSException *error; + NSDictionary *row; + NSArray *attrs; + NSString *sql; + + if ((channel = [self acquireStoreChannel]) == nil) { + [self logWithFormat:@"ERROR(%s): could not open storage channel!", + __PRETTY_FUNCTION__]; + return nil; + } + + /* generate SQL */ + + sql = @"SELECT \"c_name\", \"c_content\" FROM "; + sql = [sql stringByAppendingString:[self storeTableName]]; + + /* run SQL */ + + if ((error = [channel evaluateExpressionX:sql]) != nil) { + [self logWithFormat:@"ERROR(%s): cannot execute SQL '%@': %@", + __PRETTY_FUNCTION__, sql, error]; + [self releaseChannel:channel]; + return nil; + } + + /* fetch results */ + + result = [NSMutableDictionary dictionaryWithCapacity:128]; + attrs = [channel describeResults]; + while ((row = [channel fetchAttributes:attrs withZone:NULL]) != nil) { + NSString *cName, *cContent; + + cName = [row objectForKey:@"cName"]; + cContent = [row objectForKey:@"cContent"]; + + if (![cName isNotNull]) { + [self logWithFormat:@"ERROR: missing cName in row: %@", row]; + continue; + } + if (![cContent isNotNull]) { + [self logWithFormat:@"ERROR: missing cContent in row: %@", row]; + continue; + } + + [result setObject:cContent forKey:cName]; + } + + /* release and return result */ + + [self releaseChannel:channel]; + return result; +} + /* writing content */ - (NSString *)_formatRowValue:(id)_value { diff --git a/OGoContentStore/Version b/OGoContentStore/Version index 7254d8b0..2194d3be 100644 --- a/OGoContentStore/Version +++ b/OGoContentStore/Version @@ -2,7 +2,7 @@ MAJOR_VERSION=0 MINOR_VERSION=9 -SUBMINOR_VERSION:=12 +SUBMINOR_VERSION:=13 # v0.9.11 requires libFoundation v1.0.63 # v0.9.11 requires libNGExtensions v4.3.125 diff --git a/SOGo/Protocols/iCalHTTP/ChangeLog b/SOGo/Protocols/iCalHTTP/ChangeLog index 59ecd8c7..5f48bd54 100644 --- a/SOGo/Protocols/iCalHTTP/ChangeLog +++ b/SOGo/Protocols/iCalHTTP/ChangeLog @@ -1,8 +1,9 @@ 2004-10-19 Helge Hess + * moved fetch method to a direct action SoMethod (v0.9.3) + * SOGoICalHTTPHandler.m: some work on assembly support (v0.9.2) 2004-10-08 Helge Hess * created ChangeLog - diff --git a/SOGo/Protocols/iCalHTTP/GNUmakefile b/SOGo/Protocols/iCalHTTP/GNUmakefile index ebbde8f4..119e77a9 100644 --- a/SOGo/Protocols/iCalHTTP/GNUmakefile +++ b/SOGo/Protocols/iCalHTTP/GNUmakefile @@ -11,6 +11,7 @@ iCalHTTP_LANGUAGES = English French iCalHTTP_OBJC_FILES = \ iCalHTTPProduct.m \ SOGoICalHTTPHandler.m \ + SOGoICalFileFetch.m \ iCalHTTP_RESOURCE_FILES += \ Version \ diff --git a/SOGo/Protocols/iCalHTTP/SOGoICalFileFetch.m b/SOGo/Protocols/iCalHTTP/SOGoICalFileFetch.m new file mode 100644 index 00000000..2ec3f462 --- /dev/null +++ b/SOGo/Protocols/iCalHTTP/SOGoICalFileFetch.m @@ -0,0 +1,51 @@ +/* + 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 + +@interface SOGoICalFileFetch : WODirectAction +{ +} + +@end + +#include "SOGoICalHTTPHandler.h" +#include +#include +#include "common.h" + +@implementation SOGoICalFileFetch + +- (id)clientObject { + return [[super clientObject] aptFolderInContext:[self context]]; +} + +- (id)defaultAction { + NSArray *events; + + [self logWithFormat:@"assemble iCal events ..."]; + events = [[self clientObject] fetchAllSOGoAppointments]; + [self logWithFormat:@" events: %@", events]; + + return nil; +} + +@end /* SOGoICalFileFetch */ diff --git a/SOGo/Protocols/iCalHTTP/SOGoICalHTTPHandler.h b/SOGo/Protocols/iCalHTTP/SOGoICalHTTPHandler.h index 32fef61a..312e1407 100644 --- a/SOGo/Protocols/iCalHTTP/SOGoICalHTTPHandler.h +++ b/SOGo/Protocols/iCalHTTP/SOGoICalHTTPHandler.h @@ -30,11 +30,15 @@ Object to represent a SOGoAppointmentFolder as a single iCalendar file. */ +@class SOGoAppointmentFolder; + @interface SOGoICalHTTPHandler : NSObject { // TODO: remember for ivars: there is _one_ handler per class! Not per ctx! } +- (SOGoAppointmentFolder *)aptFolderInContext:(id)_ctx; + @end #endif /* __iCalHTTP_SOGoICalHTTPHandler_H__ */ diff --git a/SOGo/Protocols/iCalHTTP/SOGoICalHTTPHandler.m b/SOGo/Protocols/iCalHTTP/SOGoICalHTTPHandler.m index 67fd6691..2dda1c16 100644 --- a/SOGo/Protocols/iCalHTTP/SOGoICalHTTPHandler.m +++ b/SOGo/Protocols/iCalHTTP/SOGoICalHTTPHandler.m @@ -20,6 +20,7 @@ */ #include "SOGoICalHTTPHandler.h" +#include #include "common.h" #include @@ -37,11 +38,12 @@ /* clientObject */ -- (id)clientObjectInContext:(id)_ctx { +- (SOGoAppointmentFolder *)aptFolderInContext:(id)_ctx { /* The handler object is _not_ a method, its just a regular object itself! (because methods are defined on it). */ + SOGoAppointmentFolder *folder; NSArray *stack; stack = [_ctx objectTraversalStack]; @@ -55,27 +57,18 @@ return nil; } - if ([stack lastObject] != self) // TODO: hm, hm, not really OK - return [stack lastObject]; - - return [stack objectAtIndex:[stack count] - 2]; -} - -/* fetching */ - -- (NSArray *)storedNamesInContext:(id)_ctx { - /* the client object will cache the names */ - return [[self clientObjectInContext:_ctx] toOneRelationshipKeys]; + folder = ([stack lastObject] != self) // TODO: hm, hm, not really OK + ? [stack lastObject] + : [stack objectAtIndex:[stack count] - 2]; + if (![folder isKindOfClass:NSClassFromString(@"SOGoAppointmentFolder")]) { + [self logWithFormat:@"ERROR: unexpected object in stack: %@", folder]; + return nil; + } + return folder; } /* actions */ -- (id)assembleEventsInContext:(id)_ctx { - [self logWithFormat:@"assemble iCal events ..."]; - [self logWithFormat:@" names: %@", [self storedNamesInContext:_ctx]]; - return self; -} - - (id)updateEventsInContext:(id)_ctx { [self logWithFormat:@"updates iCal events from a full collection ..."]; return [NSException exceptionWithHTTPStatus:501 /* Not Implemented */ diff --git a/SOGo/Protocols/iCalHTTP/Version b/SOGo/Protocols/iCalHTTP/Version index bbf7bd63..bdf59234 100644 --- a/SOGo/Protocols/iCalHTTP/Version +++ b/SOGo/Protocols/iCalHTTP/Version @@ -1,3 +1,3 @@ # $Id: Version 368 2004-10-06 19:28:12Z znek $ -SUBMINOR_VERSION:=2 +SUBMINOR_VERSION:=3 diff --git a/SOGo/Protocols/iCalHTTP/product.plist b/SOGo/Protocols/iCalHTTP/product.plist index 51e2e8cc..8429db3f 100644 --- a/SOGo/Protocols/iCalHTTP/product.plist +++ b/SOGo/Protocols/iCalHTTP/product.plist @@ -14,10 +14,7 @@ methods = { GET = { protectedBy = "View"; - selector = { - name = "assembleEventsInContext:"; - addContextParameter = YES; - }; + actionClass = "SOGoICalFileFetch"; }; PUT = { protectedBy = "View"; diff --git a/SOGo/SoObjects/Appointments/ChangeLog b/SOGo/SoObjects/Appointments/ChangeLog index 1853d2ac..9f6a8760 100644 --- a/SOGo/SoObjects/Appointments/ChangeLog +++ b/SOGo/SoObjects/Appointments/ChangeLog @@ -1,3 +1,11 @@ +2004-10-19 Helge Hess + + * SOGoAppointmentFolder.h: added -fetchAllSOGoAppointments method + which performs a bulk fetch on all files contained in the folder + and parses all contents into an array of SOGoAppointment objects + (used in the iCal file support, try to avoid this method, expensive!) + (v0.9.13) + 2004-09-25 Helge Hess * fixed compilation on MacOSX (v0.9.12) diff --git a/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.h b/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.h index 588bf666..753e2314 100644 --- a/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.h +++ b/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.h @@ -73,6 +73,10 @@ - (id)lookupGroupFolderForUIDs:(NSArray *)_uids inContext:(id)_ctx; - (id)lookupGroupCalendarFolderForUIDs:(NSArray *)_uids inContext:(id)_ctx; +/* bulk fetches */ + +- (NSArray *)fetchAllSOGoAppointments; + @end #endif /* __Appointments_SOGoAppointmentFolder_H__ */ diff --git a/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m b/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m index 4037c09d..fadb0f29 100644 --- a/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -374,6 +374,48 @@ static NSTimeZone *MET = nil; return folder; } +/* bulk fetches */ + +- (NSArray *)fetchAllSOGoAppointments { + /* + Note: very expensive method, do not use unless absolutely required. + returns an array of SOGoAppointment objects. + + Note that we can leave out the filenames, supposed to be stored + in the 'uid' field of the iCalendar object! + */ + NSMutableArray *events; + NSDictionary *files; + NSEnumerator *contents; + NSString *content; + + /* fetch all raw contents */ + + files = [self fetchContentStringsAndNamesOfAllObjects]; + if (![files isNotNull]) return nil; + if ([files isKindOfClass:[NSException class]]) return (id)files; + + /* transform to SOGo appointments */ + + events = [NSMutableArray arrayWithCapacity:[files count]]; + contents = [files objectEnumerator]; + while ((content = [contents nextObject]) != nil) { + SOGoAppointment *event; + + event = [[SOGoAppointment alloc] initWithICalString:content]; + if (![event isNotNull]) { + [self logWithFormat:@"ERROR(%s): could not parse an iCal file!", + __PRETTY_FUNCTION__]; + continue; + } + + [events addObject:event]; + [event release]; + } + + return events; +} + /* GET */ - (id)GETAction:(WOContext *)_ctx { diff --git a/SOGo/SoObjects/Appointments/Version b/SOGo/SoObjects/Appointments/Version index 171da9b3..1df7b254 100644 --- a/SOGo/SoObjects/Appointments/Version +++ b/SOGo/SoObjects/Appointments/Version @@ -1,3 +1,5 @@ # $Id: Version,v 1.9 2004/05/19 14:30:45 helge Exp $ -SUBMINOR_VERSION:=12 +SUBMINOR_VERSION:=13 + +# v0.9.13 requires libSOGo v0.9.26 diff --git a/SOGo/SoObjects/SOGo/ChangeLog b/SOGo/SoObjects/SOGo/ChangeLog index b8d02601..1e299fc4 100644 --- a/SOGo/SoObjects/SOGo/ChangeLog +++ b/SOGo/SoObjects/SOGo/ChangeLog @@ -1,3 +1,10 @@ +2004-10-19 Helge Hess + + * SOGoFolder: added method -fetchContentStringsAndNamesOfAllObjects + which fetches the contents of all folders objects (avoid to use this + high overhead method!). Required for iCalendar file generation. + (v0.9.26) + 2004-10-08 Helge Hess * SOGoUserFolder.m: enhanced object lookup so that when a Calendar diff --git a/SOGo/SoObjects/SOGo/SOGoFolder.h b/SOGo/SoObjects/SOGo/SOGoFolder.h index df3a3301..09ab714d 100644 --- a/SOGo/SoObjects/SOGo/SOGoFolder.h +++ b/SOGo/SoObjects/SOGo/SOGoFolder.h @@ -25,8 +25,16 @@ #include +@class NSString, NSArray, NSDictionary; @class OCSFolder; +/* + SOGoFolder + + A common superclass for folders stored in OCS. Already deals with all OCS + folder specific things. +*/ + @interface SOGoFolder : SOGoObject { NSString *ocsPath; @@ -41,6 +49,11 @@ - (OCSFolder *)ocsFolderForPath:(NSString *)_path; - (OCSFolder *)ocsFolder; +/* lower level fetches */ + +- (NSArray *)fetchContentObjectNames; +- (NSDictionary *)fetchContentStringsAndNamesOfAllObjects; + @end #endif /* __SOGo_SOGoFolder_H__ */ diff --git a/SOGo/SoObjects/SOGo/SOGoFolder.m b/SOGo/SoObjects/SOGo/SOGoFolder.m index 4eee453b..1c33b944 100644 --- a/SOGo/SoObjects/SOGo/SOGoFolder.m +++ b/SOGo/SoObjects/SOGo/SOGoFolder.m @@ -67,7 +67,7 @@ } - (NSArray *)fetchContentObjectNames { - NSArray *fields, *records; + NSArray *fields, *records; fields = [NSArray arrayWithObject:@"c_name"]; records = [[self ocsFolder] fetchFields:fields matchingQualifier:nil]; @@ -79,6 +79,18 @@ return records; return [records valueForKey:@"cName"]; } +- (NSDictionary *)fetchContentStringsAndNamesOfAllObjects { + NSDictionary *files; + + files = [[self ocsFolder] fetchContentsOfAllFiles]; + if (![files isNotNull]) { + [self logWithFormat:@"ERROR(%s): fetch failed!", __PRETTY_FUNCTION__]; + return nil; + } + if ([files isKindOfClass:[NSException class]]) + return files; + return files; +} /* reflection */ diff --git a/SOGo/SoObjects/SOGo/Version b/SOGo/SoObjects/SOGo/Version index 886efe19..caf5c583 100644 --- a/SOGo/SoObjects/SOGo/Version +++ b/SOGo/SoObjects/SOGo/Version @@ -1,3 +1,5 @@ # $Id: Version 170 2004-08-11 10:45:40Z helge $ -SUBMINOR_VERSION:=25 +SUBMINOR_VERSION:=26 + +# v0.9.26 requires libOGoContentStore v0.9.13 diff --git a/SOGoLogic/ChangeLog b/SOGoLogic/ChangeLog index a8f4c88f..6caa5714 100644 --- a/SOGoLogic/ChangeLog +++ b/SOGoLogic/ChangeLog @@ -1,3 +1,7 @@ +2004-10-19 Helge Hess + + * SOGoAppointment.m: added a -description (v0.9.20) + 2004-10-17 Marcus Mueller * SOGoAppointmentICalRenderer.m: it's never wrong to escape '\', thus diff --git a/SOGoLogic/SOGoAppointment.h b/SOGoLogic/SOGoAppointment.h index 8fcf8cfd..d5cf0e0d 100644 --- a/SOGoLogic/SOGoAppointment.h +++ b/SOGoLogic/SOGoAppointment.h @@ -38,9 +38,9 @@ @interface SOGoAppointment : NSObject { - id calendar; + id calendar; iCalEvent *event; - id participants; + id participants; } - (id)initWithICalString:(NSString *)_iCal; diff --git a/SOGoLogic/SOGoAppointment.m b/SOGoLogic/SOGoAppointment.m index c0251d5e..de8dd2d0 100644 --- a/SOGoLogic/SOGoAppointment.m +++ b/SOGoLogic/SOGoAppointment.m @@ -326,4 +326,21 @@ static SaxObjectDecoder *sax = nil; return filtered; } +/* description */ + +- (void)appendAttributesToDescription:(NSMutableString *)_ms { + [_ms appendFormat:@" uid=%@", [self uid]]; + [_ms appendFormat:@" date=%@", [self startDate]]; +} + +- (NSString *)description { + NSMutableString *ms; + + ms = [NSMutableString stringWithCapacity:64]; + [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])]; + [self appendAttributesToDescription:ms]; + [ms appendString:@">"]; + return ms; +} + @end /* SOGoAppointment */ diff --git a/SOGoLogic/Version b/SOGoLogic/Version index 6225fe32..c331e5f9 100644 --- a/SOGoLogic/Version +++ b/SOGoLogic/Version @@ -1,6 +1,6 @@ # $Id$ -SUBMINOR_VERSION:=19 +SUBMINOR_VERSION:=20 # v0.9.18 requires NGExtensions v4.3.123 # v0.9.13 requires libFoundation v1.0.62 -- 2.39.5