#import <Foundation/NSObject.h>
@class NSString, NSURL, NSNumber;
+@class OCSFolderManager, OCSFolderType;
@interface OCSFolder : NSObject
{
+ OCSFolderManager *folderManager;
+ OCSFolderType *folderInfo;
+
NSNumber *folderId;
NSString *folderName;
NSString *rootName;
- (NSString *)rootName;
- (NSString *)path;
- (NSURL *)location;
-- (NSString *)folderType;
+- (NSString *)folderTypeName;
@end
// $Id$
#include "OCSFolder.h"
+#include "OCSFolderManager.h"
+#include "OCSFolderType.h"
#include "common.h"
@implementation OCSFolder
- (void)dealloc {
- [self->folderId release];
- [self->folderName release];
- [self->rootName release];
- [self->path release];
- [self->location release];
- [self->folderType release];
+ [self->folderManager release];
+ [self->folderInfo release];
+ [self->folderId release];
+ [self->folderName release];
+ [self->rootName release];
+ [self->path release];
+ [self->location release];
+ [self->folderType release];
[super dealloc];
}
return self->location;
}
-- (NSString *)folderType {
+- (NSString *)folderTypeName {
return self->folderType;
}
model and manage the tables required for a folder.
*/
-@class NSString, NSArray, NSURL;
-@class OCSChannelManager, OCSFolder;
+@class NSString, NSArray, NSURL, NSDictionary;
+@class OCSChannelManager, OCSFolder, OCSFolderType;
@interface OCSFolderManager : NSObject
{
OCSChannelManager *channelManager;
- NSURL *folderInfoLocation;
+ NSDictionary *nameToType;
+ NSURL *folderInfoLocation;
}
+ (id)defaultFolderManager;
- (OCSFolder *)folderAtPath:(NSString *)_path;
+/* folder types */
+
+- (OCSFolderType *)folderTypeWithName:(NSString *)_name;
+
/* cache management */
- (void)reset;
Required database schema:
<arbitary table>
- path
- path1, path2, path3... [quickPathCount times]
- folderName
+ c_path
+ c_path1, path2, path3... [quickPathCount times]
+ c_foldername
TODO:
- add a local cache?
@implementation OCSFolderManager
static OCSFolderManager *fm = nil;
-static BOOL debugOn = NO;
-static BOOL debugSQLGen = NO;
-static int quickPathCount = 4;
-static NSArray *emptyArray = nil;
+static BOOL debugOn = NO;
+static BOOL debugSQLGen = NO;
+static BOOL debugPathTraversal = NO;
+static int quickPathCount = 4;
+static NSArray *emptyArray = nil;
+static NSString *OCSPathColumnName = @"c_path";
+static NSString *OCSPathRecordName = @"cPath";
+static NSString *OCSTypeColumnName = @"c_folder_type";
+static NSString *OCSTypeRecordName = @"cFolderType";
+static NSString *OCSGenericFolderTypeName = @"Container";
+static const char *OCSPathColumnPattern = "c_path%i";
+ (void)initialize {
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
if ((self = [super init])) {
self->channelManager = [[OCSChannelManager defaultChannelManager] retain];
self->folderInfoLocation = [_url retain];
+
+ self->nameToType =
+ [[NSDictionary alloc] initWithObjectsAndKeys:
+ [OCSFolderType defaultCalendarFolderType],
+ @"appointment", nil];
}
return self;
}
- (void)dealloc {
+ [self->nameToType release];
[self->folderInfoLocation release];
[self->channelManager release];
[super dealloc];
NSString *pathColumn;
unsigned char buf[32];
- sprintf(buf, "\"path%i\"", (i + 1));
+ sprintf(buf, OCSPathColumnPattern, (i + 1));
pathColumn = [[NSString alloc] initWithCString:buf];
/* Note: the AND addition must be inside the if's for non-exact stuff */
if ([sql length] > 0) [sql appendString:@" AND "];
[sql appendString:pathColumn];
[sql appendString:@" IS NULL"];
- //[self logWithFormat:@"BE EXACT, NULL columns"];
+ if (debugPathTraversal) [self logWithFormat:@"BE EXACT, NULL columns"];
}
else if (_directSubs) {
/* fetch immediate subfolders */
if (i == count) {
/* if it is a direct subfolder, the next path cannot be empty */
[sql appendString:@" IS NOT NULL"];
- //[self logWithFormat:@"DIRECT SUBS, first level"];
+ if (debugPathTraversal)
+ [self logWithFormat:@"DIRECT SUBS, first level"];
}
else {
/* but for 'direct' subfolders, all following things must be empty */
[sql appendString:@" IS NULL"];
- //[self logWithFormat:@"DIRECT SUBS, lower level"];
+ if (debugPathTraversal)
+ [self logWithFormat:@"DIRECT SUBS, lower level"];
}
}
}
if (_beExact && (count > quickPathCount)) {
- [sql appendString:@" AND \"folderName\" = '"];
+ [sql appendString:@" AND \"c_foldername\" = '"];
[sql appendString:[_names lastObject]];
[sql appendString:@"'"];
}
return nil;
sql = [NSMutableString stringWithCapacity:256];
- [sql appendString:@"SELECT \"path\" FROM "];
+ [sql appendString:@"SELECT \"c_path\" FROM "];
[sql appendString:[self folderInfoTableName]];
[sql appendString:@" WHERE "];
[sql appendString:ws];
for (i = 0, count = [_records count]; i < count; i++) {
NSString *recName;
- recName = [[_records objectAtIndex:i] objectForKey:@"path"];
- [self logWithFormat:@"check '%@' vs '%@' ...", name, recName];
+ recName = [[_records objectAtIndex:i] objectForKey:OCSPathRecordName];
+#if 0
+ [self logWithFormat:@"check '%@' vs '%@' (%@)...",
+ name, recName,[_records objectAtIndex:i]];
+#endif
+
if ([name isEqualToString:recName])
return [_records objectAtIndex:i];
}
if (count == 1) {
NSString *sname;
- sname = [[records objectAtIndex:0] objectForKey:@"path"];
+ sname = [[records objectAtIndex:0] objectForKey:OCSPathRecordName];
return [fname isEqualToString:sname];
}
for (i = 0; i < count; i++) {
NSString *sname, *spath;
- sname = [[records objectAtIndex:0] objectForKey:@"path"];
+ sname = [[records objectAtIndex:0] objectForKey:OCSPathRecordName];
if (![sname hasPrefix:fname]) /* does not match at all ... */
continue;
sql = [NSMutableString stringWithCapacity:256];
[sql appendString:@"SELECT "];
- [sql appendString:@"\"folderid\", \"path\", \"location\", \"foldertype\""];
+ [sql appendString:
+ @"\"c_folder_id\", \"c_path\", \"c_location\", \"c_folder_type\""];
[sql appendString:@" FROM "];
[sql appendString:[self folderInfoTableName]];
[sql appendString:@" WHERE "];
return nil;
}
+/* folder types */
+
+- (OCSFolderType *)folderTypeWithName:(NSString *)_name {
+ if ([_name length] == 0)
+ _name = OCSGenericFolderTypeName;
+
+ return [self->nameToType objectForKey:_name];
+}
+
/* cache management */
- (void)reset {
{
NSString *blobTablePattern; // eg 'SOGo_$folderId$_blob
NSString *quickTablePattern; // eg 'SOGo_$folderId$_quick
- NSDictionary *fields;
+ NSDictionary *fields; // maps a name to OCSFieldInfo
EOQualifier *folderQualifier; // to further limit the table set
}
++ (id)defaultCalendarFolderType;
+
/* operations */
- (NSString *)blobTableNameForFolder:(OCSFolder *)_folder;
@implementation OCSFolderType
+static OCSFolderType *calendarType = nil;
+
+- (id)initAsCalendarFolderType {
+ // TODO: should be moved to a plist file
+ if ((self = [super init])) {
+ self->blobTablePattern = @"SOGo_$folderId$_blob";
+ self->quickTablePattern = @"SOGo_$folderId$_quick";
+ self->folderQualifier = nil; // a table per folder
+
+ // TODO: which fields?
+ }
+ return self;
+}
+
++ (id)defaultCalendarFolderType {
+ if (calendarType == nil)
+ calendarType = [[self alloc] init];
+ return calendarType;
+}
+
- (void)dealloc {
[self->blobTablePattern release];
[self->quickTablePattern release];
CREATE SEQUENCE SOGo_folder_info_seq;
+DROP TABLE SOGo_folder_info;
+
CREATE TABLE SOGo_folder_info (
- folderId INTEGER
+ c_folder_id INTEGER
DEFAULT nextval('SOGo_folder_info_seq')
NOT NULL
PRIMARY KEY, -- the primary key
- path VARCHAR(255) NOT NULL, -- the full path to the folder 'xyz/Cal'
- path1 VARCHAR(255) NOT NULL, -- individual parts (for fast queries)
- path2 VARCHAR(255) NULL, -- individual parts (for fast queries)
- path3 VARCHAR(255) NULL, -- individual parts (for fast queries)
- path4 VARCHAR(255) NULL, -- individual parts (for fast queries)
- folderName VARCHAR(255) NOT NULL, -- last path component
- location VARCHAR(2048) NOT NULL, -- URL to database of the folder
- folderType VARCHAR(255) NOT NULL -- the folder type ...
+ c_path VARCHAR(255) NOT NULL, -- the full path to the folder
+ c_path1 VARCHAR(255) NOT NULL, -- individual parts (for fast queries)
+ c_path2 VARCHAR(255) NULL, -- individual parts (for fast queries)
+ c_path3 VARCHAR(255) NULL, -- individual parts (for fast queries)
+ c_path4 VARCHAR(255) NULL, -- individual parts (for fast queries)
+ c_foldername VARCHAR(255) NOT NULL, -- last path component
+ c_location VARCHAR(2048) NOT NULL, -- URL to database of the folder
+ c_folder_type VARCHAR(255) NOT NULL -- the folder type ...
);
INSERT INTO SOGo_folder_info
- ( path, path1, path2, path3, path4, foldername, location, foldertype )
+ ( c_path, c_path1, c_path2, c_path3, c_path4, c_foldername,
+ c_location, c_folder_type )
VALUES
( '/Users',
'Users',
'http://OGo:OGo@localhost/test', 'Container' );
INSERT INTO SOGo_folder_info
- ( path, path1, path2, path3, path4, foldername, location, foldertype )
+ ( c_path, c_path1, c_path2, c_path3, c_path4, c_foldername,
+ c_location, c_folder_type )
VALUES
( '/Users/helge',
'Users',
'http://OGo:OGo@localhost/test', 'Container' );
INSERT INTO SOGo_folder_info
- ( path, path1, path2, path3, path4, foldername, location, foldertype )
+ ( c_path, c_path1, c_path2, c_path3, c_path4, c_foldername,
+ c_location, c_folder_type )
VALUES
( '/Users/helge/Calendar',
'Users',