// // Folder.m // OpenStack // // Created by Mike Mayo on 12/7/10. // The OpenStack project is provided under the Apache 2.0 license. // #import "Folder.h" #import "StorageObject.h" #import "NSObject+NSCoding.h" #import "PithosUtilities.h" @implementation Folder @synthesize name, parent, folders, objects, metadata, sharing, contentType; + (id)folder { Folder *folder = [[[self alloc] init] autorelease]; folder.folders = [[[NSMutableDictionary alloc] init] autorelease]; folder.objects = [[[NSMutableDictionary alloc] init] autorelease]; return folder; } #pragma mark - #pragma mark Serialization - (id)init { if (self = [super init]) { self.folders = [[[NSMutableDictionary alloc] init] autorelease]; self.objects = [[[NSMutableDictionary alloc] init] autorelease]; } return self; } - (void)encodeWithCoder:(NSCoder *)coder { [self autoEncodeWithCoder:coder]; /* [coder encodeObject:name forKey:@"name"]; [coder encodeObject:parent forKey:@"parent"]; [coder encodeObject:folders forKey:@"folders"]; [coder encodeObject:objects forKey:@"objects"]; */ } - (id)initWithCoder:(NSCoder *)coder { if (self = [super init]) { [self autoDecode:coder]; /* name = [[coder decodeObjectForKey:@"name"] retain]; parent = [[coder decodeObjectForKey:@"parent"] retain]; folders = [[coder decodeObjectForKey:@"folders"] retain]; objects = [[coder decodeObjectForKey:@"objects"] retain]; */ } return self; } - (void)setObjects:(NSMutableDictionary *)objs { if (self.objects != objs) { [objects release]; NSMutableDictionary *folderedFiles = [[NSMutableDictionary alloc] init]; NSMutableDictionary *files = [[NSMutableDictionary alloc] init]; folders = [[NSMutableDictionary alloc] init]; for (NSString *key in objs) { StorageObject *object = [objs objectForKey:key]; BOOL objectHasTrailingSlash = NO; if ([object.name hasSuffix:@"/"]) { objectHasTrailingSlash = YES; object.name = [object.name substringToIndex:(object.name.length - 1)]; } NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"/" options:NSRegularExpressionCaseInsensitive error:nil]; NSInteger matches = [regex numberOfMatchesInString:object.name options:0 range:NSMakeRange(0, [object.name length])]; if (matches > 0) { // build up the folder structure NSMutableArray *components = [NSMutableArray arrayWithArray:[object.name componentsSeparatedByString:@"/"]]; NSString *folderName = [components objectAtIndex:0]; object.name = [components lastObject]; if (objectHasTrailingSlash) object.name = [object.name stringByAppendingString:@"/"]; for (int i = [components count] - 2; i > 0; i--) { object.name = [NSString stringWithFormat:@"%@/%@", [components objectAtIndex:i], object.name]; } if (![folderedFiles objectForKey:folderName]) { [folderedFiles setObject:[NSMutableDictionary dictionary] forKey:folderName]; } NSMutableDictionary *folderFiles = [folderedFiles objectForKey:folderName]; [folderFiles setObject:object forKey:object.name]; } else if ([PithosUtilities isContentTypeDirectory:object.contentType]) { Folder *folder = [[Folder alloc] init]; if (objectHasTrailingSlash) folder.name = [NSString stringWithFormat:@"%@/", object.name]; else folder.name = object.name; folder.parent = self; folder.metadata = object.metadata; folder.sharing = object.sharing; folder.contentType = object.contentType; [self.folders setObject:folder forKey:folder.name]; [folder release]; } else { // put the files in this folder if (objectHasTrailingSlash) object.name = [object.name stringByAppendingString:@"/"]; [files setObject:object forKey:object.name]; } } // take the foldered files and recursively build the rest of the folder structure NSArray *keys = [folderedFiles allKeys]; for (int i = 0; i < [keys count]; i++) { NSString *folderName = [keys objectAtIndex:i]; NSMutableDictionary *folderFiles = [folderedFiles objectForKey:folderName]; Folder *folder = [[Folder alloc] init]; folder.name = folderName; folder.parent = self; folder.objects = folderFiles; StorageObject *object = [objs objectForKey:folderName]; if ([PithosUtilities isContentTypeDirectory:object.contentType]) { folder.metadata = object.metadata; folder.sharing = object.sharing; folder.contentType = object.contentType; } else { folder.metadata = [NSMutableDictionary dictionary]; } [self.folders setObject:folder forKey:folder.name]; [folder release]; } [folderedFiles release]; objects = files; } } - (NSArray *)sortedContents { NSMutableArray *contents = [[NSMutableArray alloc] initWithArray:[self.folders allValues]]; [contents addObjectsFromArray:[self.objects allValues]]; if (!sortedContents || ![sortedContents isEqualToArray:contents]) { sortedContents = [[NSArray alloc] initWithArray:[contents sortedArrayUsingSelector:@selector(compare:)]]; } [contents release]; return sortedContents; } - (NSComparisonResult)compare:(Folder *)aFolder { return [self.name caseInsensitiveCompare:aFolder.name]; } - (NSString *)fullPath { NSString *result = self.name; if (parent) { result = [NSString stringWithFormat:@"%@/%@", [parent fullPath], self.name]; } if (!result) { result = @""; } return result; } -(void)dealloc { [name release]; [parent release]; [folders release]; [sharing release]; [objects release]; [sortedContents release]; [contentType release]; [super dealloc]; } @end