From 6d5c44d31f1ca2f68564d1a87def3074d6da715a Mon Sep 17 00:00:00 2001 From: helge Date: Wed, 11 Aug 2004 15:58:46 +0000 Subject: [PATCH] git-svn-id: http://svn.opengroupware.org/SOGo/trunk@183 d1b88da0-ebda-0310-925b-ed51d893ca5b --- SOGo/SoObjects/Appointments/ChangeLog | 4 + .../Appointments/SOGoAppointmentFolder.m | 1 + .../Appointments/SOGoGroupAppointmentFolder.m | 122 +++++++++++++++++- SOGo/SoObjects/Appointments/Version | 2 +- 4 files changed, 126 insertions(+), 3 deletions(-) diff --git a/SOGo/SoObjects/Appointments/ChangeLog b/SOGo/SoObjects/Appointments/ChangeLog index 14a1ca08..7141aa20 100644 --- a/SOGo/SoObjects/Appointments/ChangeLog +++ b/SOGo/SoObjects/Appointments/ChangeLog @@ -1,5 +1,9 @@ 2004-08-11 Helge Hess + * SOGoGroupAppointmentFolder: can merge input folders, tracks conflicts + in 'conflicts' key of the record (should be displayed somehow in the + UI) (v0.9.3) + * v0.9.2 * SOGoAppointmentFolder.m, SOGoGroupAppointmentFolder: added diff --git a/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m b/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m index 4d3dd005..be8734b4 100644 --- a/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -205,6 +205,7 @@ static NSTimeZone *MET = nil; - (NSArray *)fetchCoreInfosFrom:(NSCalendarDate *)_startDate to:(NSCalendarDate *)_endDate { + /* this is the primary API */ OCSFolder *folder; if ((folder = [self ocsFolder]) == nil) { diff --git a/SOGo/SoObjects/Appointments/SOGoGroupAppointmentFolder.m b/SOGo/SoObjects/Appointments/SOGoGroupAppointmentFolder.m index 06b32b33..a3eaa57a 100644 --- a/SOGo/SoObjects/Appointments/SOGoGroupAppointmentFolder.m +++ b/SOGo/SoObjects/Appointments/SOGoGroupAppointmentFolder.m @@ -37,12 +37,129 @@ return [[self container] valueForKey:@"uids"]; } +/* merging */ + +- (BOOL)doesRecord:(NSDictionary *)_rec conflictWith:(NSDictionary *)_other { + if (_rec == _other) + return NO; + if ([_rec isEqual:_other]) + return NO; + + return YES; +} + +- (NSDictionary *)_registerConflictingRecord:(NSDictionary *)_other + inRecord:(NSDictionary *)_record +{ + NSMutableArray *conflicts; + + if (_record == nil) return _other; + if (_other == nil) return _record; + + if ((conflicts = [_record objectForKey:@"conflicts"]) == nil) { + NSMutableDictionary *md; + + md = [[_record copy] autorelease]; + conflicts = [NSMutableArray arrayWithCapacity:4]; + [md setObject:conflicts forKey:@"conflicts"]; + _record = md; + } + [conflicts addObject:_other]; + return _record; +} + /* functionality */ +- (NSArray *)fetchCoreInfosFrom:(NSCalendarDate *)_startDate + to:(NSCalendarDate *)_endDate + memberFolder:(id)_folder +{ + SOGoAppointmentFolder *aptFolder; + + if (![_folder isNotNull]) + return nil; + + aptFolder = [_folder lookupName:@"Calendar" inContext:nil acquire:NO]; + if (![aptFolder isNotNull]) { + [self logWithFormat:@"ERROR: member folder no 'Calendar': %@", _folder]; + return nil; + } + + if (![aptFolder respondsToSelector:@selector(fetchCoreInfosFrom:to:)]) { + [self logWithFormat:@"ERROR: folder does not implemented required API: %@", + _folder]; + return nil; + } + + return [aptFolder fetchCoreInfosFrom:_startDate to:_endDate]; +} + +- (NSArray *)fetchCoreInfosFrom:(NSCalendarDate *)_startDate + to:(NSCalendarDate *)_endDate + memberFolders:(NSArray *)_folders +{ + NSMutableArray *result; + NSMutableDictionary *uidToRecord; + unsigned i, count; + + if ((count = [_folders count]) == 0) + return [NSArray array]; + if (count == 1) { + return [self fetchCoreInfosFrom:_startDate to:_endDate + memberFolder:[_folders objectAtIndex:0]]; + } + + uidToRecord = [NSMutableDictionary dictionaryWithCapacity:(7 * count)]; + result = [NSMutableArray arrayWithCapacity:(7 * count)]; + for (i = 0; i < count; i++) { + id results; + NSDictionary *record; + + results = [self fetchCoreInfosFrom:_startDate to:_endDate + memberFolder:[_folders objectAtIndex:i]]; + if (![results isNotNull]) continue; + + results = [results objectEnumerator]; + while ((record = [results nextObject])) { + NSString *uid; + NSDictionary *existingRecord; + + uid = [record objectForKey:@"uid"]; + if (![uid isNotNull]) { + [self logWithFormat:@"WARNING: record without uid: %@", result]; + [result addObject:record]; + continue; + } + + if ((existingRecord = [uidToRecord objectForKey:uid]) == nil) { + /* record not yet in result set */ + [uidToRecord setObject:record forKey:uid]; + [result addObject:record]; + } + else if ([self doesRecord:existingRecord conflictWith:record]) { + /* record already registered and it conflicts (diff values) */ + NSDictionary *newRecord; + int idx; + + newRecord = [self _registerConflictingRecord:record + inRecord:existingRecord]; + [uidToRecord setObject:newRecord forKey:uid]; + + if ((idx = [result indexOfObject:existingRecord]) != NSNotFound) + [result replaceObjectAtIndex:idx withObject:newRecord]; + } + else { + /* record already registered, but values in sync, nothing to do */ + } + } + } + return result; +} + - (NSArray *)fetchCoreInfosFrom:(NSCalendarDate *)_startDate to:(NSCalendarDate *)_endDate { -#warning TODO: implement aggregation based on the container + /* this is the main dispatcher method */ NSArray *folders; if ((folders = [[self container] valueForKey:@"memberFolders"]) == nil) { @@ -50,7 +167,8 @@ return nil; } - return [NSArray array]; + return [self fetchCoreInfosFrom:_startDate to:_endDate + memberFolders:folders]; } @end /* SOGoGroupAppointmentFolder */ diff --git a/SOGo/SoObjects/Appointments/Version b/SOGo/SoObjects/Appointments/Version index d277318d..58d50ae7 100644 --- a/SOGo/SoObjects/Appointments/Version +++ b/SOGo/SoObjects/Appointments/Version @@ -1,3 +1,3 @@ # $Id: Version,v 1.9 2004/05/19 14:30:45 helge Exp $ -SUBMINOR_VERSION:=2 +SUBMINOR_VERSION:=3 -- 2.39.2