From 190ca58217d0e784ef6ddf16dee10e4c03679939 Mon Sep 17 00:00:00 2001 From: helge Date: Tue, 12 Jul 2005 15:00:36 +0000 Subject: [PATCH] implemented profile saving git-svn-id: http://svn.opengroupware.org/SOGo/trunk@727 d1b88da0-ebda-0310-925b-ed51d893ca5b --- SOGo/SoObjects/SOGo/AgenorUserDefaults.h | 1 + SOGo/SoObjects/SOGo/AgenorUserDefaults.m | 158 +++++++++++++++++++++-- SOGo/SoObjects/SOGo/ChangeLog | 5 + SOGo/SoObjects/SOGo/Version | 2 +- 4 files changed, 152 insertions(+), 14 deletions(-) diff --git a/SOGo/SoObjects/SOGo/AgenorUserDefaults.h b/SOGo/SoObjects/SOGo/AgenorUserDefaults.h index 667bdc8a..d2751389 100644 --- a/SOGo/SoObjects/SOGo/AgenorUserDefaults.h +++ b/SOGo/SoObjects/SOGo/AgenorUserDefaults.h @@ -41,6 +41,7 @@ NSString *uid; NSArray *fieldNames; + NSDictionary *attributes; NSMutableDictionary *values; NSCalendarDate *lastFetch; diff --git a/SOGo/SoObjects/SOGo/AgenorUserDefaults.m b/SOGo/SoObjects/SOGo/AgenorUserDefaults.m index 5941b493..dcab5b00 100644 --- a/SOGo/SoObjects/SOGo/AgenorUserDefaults.m +++ b/SOGo/SoObjects/SOGo/AgenorUserDefaults.m @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "common.h" @implementation AgenorUserDefaults @@ -48,10 +50,11 @@ static NSString *uidColumnName = @"uid"; } - (void)dealloc { - [self->lastFetch release]; - [self->parent release]; - [self->url release]; - [self->uid release]; + [self->attributes release]; + [self->lastFetch release]; + [self->parent release]; + [self->url release]; + [self->uid release]; [super dealloc]; } @@ -70,6 +73,31 @@ static NSString *uidColumnName = @"uid"; /* operation */ +- (void)_loadAttributes:(NSArray *)_attrs { + NSMutableArray *fields; + NSMutableDictionary *attrmap; + unsigned i, count; + + fields = [[NSMutableArray alloc] initWithCapacity:16]; + attrmap = [[NSMutableDictionary alloc] initWithCapacity:16]; + for (i = 0, count = [_attrs count]; i < count; i++) { + EOAttribute *attr; + NSString *name; + + attr = [_attrs objectAtIndex:i]; + name = [attr valueForKey:@"name"]; + [attrmap setObject:attr forKey:name]; + + if (![name isEqual:uidColumnName]) + [fields addObject:name]; + } + + ASSIGNCOPY(self->fieldNames, fields); + ASSIGNCOPY(self->attributes, attrmap); + [attrmap release]; + [fields release]; +} + - (BOOL)primaryFetchProfile { GCSChannelManager *cm; EOAdaptorChannel *channel; @@ -77,7 +105,6 @@ static NSString *uidColumnName = @"uid"; NSException *ex; NSString *sql; NSArray *attrs; - NSMutableArray *fields; cm = [GCSChannelManager defaultChannelManager]; if ((channel = [cm acquireOpenChannelForURL:[self tableURL]]) == nil) { @@ -104,17 +131,13 @@ static NSString *uidColumnName = @"uid"; /* fetch schema */ attrs = [channel describeResults:NO /* don't beautify */]; - - fields = [[attrs valueForKey:@"name"] mutableCopy]; - [fields removeObject:uidColumnName]; - ASSIGNCOPY(self->fieldNames, fields); - [fields release]; fields =nil; + [self _loadAttributes:attrs]; /* fetch values */ row = [channel fetchAttributes:attrs withZone:NULL]; [channel cancelFetch]; - + /* remember values */ [self->values release]; self->values = nil; @@ -131,6 +154,97 @@ static NSString *uidColumnName = @"uid"; return YES; } +- (NSString *)generateSQLForUpdate { + NSMutableString *sql; + unsigned i, count; + + if ([self->values count] == 0) + return nil; + + sql = [NSMutableString stringWithCapacity:2048]; + + [sql appendString:@"UPDATE "]; + [sql appendString:[[self tableURL] gcsTableName]]; + [sql appendString:@" SET "]; + + for (i = 0, count = [self->fieldNames count]; i < count; i++) { + EOAttribute *attr; + NSString *name; + id value; + + name = [self->fieldNames objectAtIndex:i]; + value = [self->values objectForKey:name]; + attr = [self->attributes objectForKey:name]; + + if (i != 0) [sql appendString:@", "]; + [sql appendString:[attr columnName]]; + + if ([value isNotNull]) { + /* a rather limited set of supported value types */ + + if ([[attr externalType] hasPrefix:@"int"]) + [sql appendFormat:@" = %i", [value intValue]]; + else { + // TODO: any other escaping?! move to adaptor? + value = [value stringValue]; + value = [value stringByReplacingString:@"'" withString:@"''"]; + [sql appendString:@" = '"]; + [sql appendString:value]; + [sql appendString:@"'"]; + } + } + else + [sql appendString:@" = NULL"]; + } + + [sql appendString:@" WHERE "]; + [sql appendString:uidColumnName]; + [sql appendString:@" = '"]; + [sql appendString:[self uid]]; + [sql appendString:@"'"]; + return sql; +} + +- (BOOL)primaryStoreProfile { + GCSChannelManager *cm; + EOAdaptorChannel *channel; + NSException *ex; + NSString *sql; + + cm = [GCSChannelManager defaultChannelManager]; + if ((channel = [cm acquireOpenChannelForURL:[self tableURL]]) == nil) { + [self errorWithFormat:@"failed to acquire channel for URL: %@", + [self tableURL]]; + return NO; + } + + /* run SQL */ + + sql = [self generateSQLForUpdate]; + if ((ex = [channel evaluateExpressionX:sql]) != nil) { + [self errorWithFormat:@"could not run SQL '%@': %@", sql, ex]; + [cm releaseChannel:channel]; + return NO; + } + + /* commit */ + + ex = nil; + if ([[channel adaptorContext] hasOpenTransaction]) + ex = [channel evaluateExpressionX:@"COMMIT TRANSACTION"]; + + [cm releaseChannel:channel]; + + if (ex != nil) { + [self errorWithFormat:@"could not commit transaction for update: %@", ex]; + return NO; + } + + self->defFlags.modified = 0; + return YES; +} + + - (BOOL)fetchProfile { if (self->values != nil) return YES; @@ -200,9 +314,27 @@ static NSString *uidColumnName = @"uid"; - (BOOL)synchronize { if (!self->defFlags.modified) /* was not modified */ return YES; + + /* ensure fetched data (more or less guaranteed by modified!=0) */ + if (![self fetchProfile]) + return NO; + + /* store */ + if (![self primaryStoreProfile]) { + [self primaryFetchProfile]; + return NO; + } + + /* refetch */ + return [self primaryFetchProfile]; +} - [self logWithFormat:@"TODO: sync!"]; - return NO; +- (void)flush { + [self->values release]; self->values = nil; + [self->fieldNames release]; self->fieldNames = nil; + [self->attributes release]; self->attributes = nil; + [self->lastFetch release]; self->lastFetch = nil; + self->defFlags.modified = 0; } /* typed accessors */ diff --git a/SOGo/SoObjects/SOGo/ChangeLog b/SOGo/SoObjects/SOGo/ChangeLog index 453d72d3..2b5c2d6e 100644 --- a/SOGo/SoObjects/SOGo/ChangeLog +++ b/SOGo/SoObjects/SOGo/ChangeLog @@ -1,3 +1,8 @@ +2005-07-12 Helge Hess + + * AgenorUserDefaults.m: implemented saving of changed profiles + (v0.9.47) + 2005-07-12 Marcus Mueller * AgenorUserManager.[hm]: new API for extracting UIDs from iCalPersons diff --git a/SOGo/SoObjects/SOGo/Version b/SOGo/SoObjects/SOGo/Version index 09850cc9..cd83313c 100644 --- a/SOGo/SoObjects/SOGo/Version +++ b/SOGo/SoObjects/SOGo/Version @@ -1,6 +1,6 @@ # version file -SUBMINOR_VERSION:=46 +SUBMINOR_VERSION:=47 # v0.9.34 requires libGDLContentStore v4.5.26 # v0.9.26 requires libOGoContentStore v0.9.13 -- 2.39.5