//
-// PithosNode.m
+// PithosAccountNode.m
// pithos-macos
//
// Copyright 2011 GRNET S.A. All rights reserved.
#import "PithosAccountNode.h"
#import "PithosContainerNode.h"
#import "ASIPithosAccountRequest.h"
+#import "ASIPithosAccount.h"
#import "ASIPithosContainer.h"
#import "ASIDownloadCache.h"
+#import "PithosUtilities.h"
+
+static NSImage *sharedIcon = nil;
@implementation PithosAccountNode
+@synthesize pithosAccount;
+
++ (void)initialize {
+ if (self == [PithosAccountNode class])
+ sharedIcon = [[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kUserIcon)] retain];
+}
#pragma mark -
#pragma mark Object Lifecycle
-- (id)init {
- if ((self = [super init])) {
- refreshing = NO;
- }
- return self;
-}
-
- (void)dealloc {
+ [accountRequest clearDelegatesAndCancel];
+ [accountRequest release];
+ [refreshMetadataAccountRequest clearDelegatesAndCancel];
+ [refreshMetadataAccountRequest release];
+ [applyMetadataAccountRequest clearDelegatesAndCancel];
+ [applyMetadataAccountRequest release];
[containers release];
+ [pithosAccount release];
[super dealloc];
}
#pragma mark -
+#pragma mark Properties
+
+- (NSString *)url {
+ if (url == nil)
+ url = [[NSString alloc] initWithFormat:@"%@%@",
+ (sharingAccount ? [ASIPithosRequest storageURLWithAuthUser:sharingAccount] : [ASIPithosRequest storageURL]),
+ (shared ? @"?shared" : @"")];
+ return url;
+}
+
+- (NSArray *)children {
+ @synchronized(self) {
+ switch (freshness) {
+ case PithosNodeStateFresh:
+ break;
+ case PithosNodeStateRefreshNeeded:
+ freshness = PithosNodeStateRefreshing;
+ accountRequest = [[ASIPithosAccountRequest listContainersRequestWithLimit:0
+ marker:nil
+ shared:shared
+ until:nil] retain];
+ if (sharingAccount)
+ [accountRequest setRequestUserFromDefaultTo:sharingAccount];
+ accountRequest.delegate = self;
+ accountRequest.didFinishSelector = @selector(accountRequestFinished:);
+ accountRequest.didFailSelector = @selector(accountRequestFailed:);
+ if (!forcedRefresh)
+ accountRequest.downloadCache = [ASIDownloadCache sharedCache];
+ [[PithosUtilities prepareRequest:accountRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous];
+ break;
+ case PithosNodeStateRefreshing:
+ break;
+ case PithosNodeStateRefreshFinished:
+ if (newChildren) {
+ [children release];
+ children = newChildren;
+ newChildren = nil;
+ }
+ freshness = PithosNodeStateFresh;
+ default:
+ break;
+ }
+ return children;
+ }
+}
+
+- (NSString *)displayName {
+ if (displayName == nil)
+ return [NSString stringWithString:(sharingAccount ? sharingAccount : @"account")];
+ return [[displayName copy] autorelease];
+}
+
+- (NSImage *)icon {
+ if (icon == nil)
+ icon = [sharedIcon retain];
+ return icon;
+}
+
+#pragma mark -
#pragma mark ASIHTTPRequestDelegate
-- (void)requestFinished:(ASIPithosAccountRequest *)accountRequest {
+- (void)accountRequestFinished:(ASIPithosAccountRequest *)request {
NSLog(@"URL: %@", [accountRequest url]);
NSLog(@"cached: %d", [accountRequest didUseCachedResponse]);
+
+ self.pithosAccount = [accountRequest account];
NSArray *someContainers = [accountRequest containers];
if (containers == nil) {
if (!accountRequest.didUseCachedResponse || ([containers count] != [someContainers count]) || !children) {
// Save new children
NSLog(@"using newChildren");
- NSMutableArray *newChildren = [NSMutableArray array];
+ newChildren = [[NSMutableArray alloc] init];
+ NSMutableIndexSet *keptNodes = [NSMutableIndexSet indexSet];
for (ASIPithosContainer *container in containers) {
PithosContainerNode *node = [[[PithosContainerNode alloc] initWithPithosContainer:container] autorelease];
+ node.parent = self;
+ node.shared = shared;
+ node.sharingAccount = sharingAccount;
if (children) {
NSUInteger oldIndex = [children indexOfObject:node];
- if (oldIndex != NSNotFound)
+ if (oldIndex != NSNotFound) {
// Use the same pointer value, if possible
node = [children objectAtIndex:oldIndex];
+ node.pithosContainer = container;
+ [keptNodes addIndex:oldIndex];
+ }
}
[newChildren addObject:node];
}
- [children release];
- children = [newChildren retain];
+ [[children objectsAtIndexes:
+ [[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [children count])] indexesPassingTest:^(NSUInteger idx, BOOL *stop){
+ if ([keptNodes containsIndex:idx])
+ return NO;
+ return YES;
+ }]] makeObjectsPerformSelector:@selector(pithosNodeWillBeRemoved)];
}
- // Else cache was used and all results were fetched during this request, so previousChildren can be reused
+ // Else cache was used and all results were fetched during this request, so existing children can be reused
+ [accountRequest release];
+ accountRequest = nil;
[containers release];
containers = nil;
- // XXX sort children based on preferences
- refreshing = NO;
+ forcedRefresh = NO;
+ @synchronized(self) {
+ freshness = PithosNodeStateRefreshFinished;
+ }
// Notify observers that children are updated
[[NSNotificationCenter defaultCenter] postNotificationName:@"PithosAccountNodeChildrenUpdated" object:self];
} else {
+ [accountRequest release];
// Do an additional request to fetch more objects
- ASIPithosAccountRequest *newAccountRequest = [ASIPithosAccountRequest listContainersRequestWithLimit:0
- marker:[[someContainers lastObject] name]
- shared:NO
- until:nil];
- newAccountRequest.delegate = self;
- newAccountRequest.downloadCache = [ASIDownloadCache sharedCache];
- [newAccountRequest startAsynchronous];
+ accountRequest = [[ASIPithosAccountRequest listContainersRequestWithLimit:0
+ marker:[[someContainers lastObject] name]
+ shared:shared
+ until:nil] retain];
+ if (sharingAccount)
+ [accountRequest setRequestUserFromDefaultTo:sharingAccount];
+ accountRequest.delegate = self;
+ if (!forcedRefresh)
+ accountRequest.downloadCache = [ASIDownloadCache sharedCache];
+ [[PithosUtilities prepareRequest:accountRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous];
}
}
-- (void)requestFailed:(ASIPithosAccountRequest *)accountRequest {
- // XXX do something on error, cleanup
- NSLog(@"error:%@", [accountRequest error]);
+- (void)accountRequestFailed:(ASIPithosAccountRequest *)request {
+ [PithosUtilities httpRequestErrorAlertWithRequest:request];
+ [newChildren release];
+ newChildren = nil;
+ [accountRequest release];
+ accountRequest = nil;
[containers release];
containers = nil;
- childrenDirty = YES;
- refreshing = NO;
+ forcedRefresh = NO;
+ @synchronized(self) {
+ freshness = PithosNodeStateRefreshNeeded;
+ }
}
-#pragma mark -
-#pragma mark Properties
-
-- (NSString *)url {
- if (url == nil)
- url = [[ASIPithosRequest storageURL] copy];
- return url;
+- (void)accountMetadataRequestFinished:(ASIPithosAccountRequest *)request {
+ NSLog(@"URL: %@", [request url]);
+ NSLog(@"cached: %d", [request didUseCachedResponse]);
+
+ if ([request isEqualTo:applyMetadataAccountRequest]) {
+ @synchronized(self) {
+ [applyMetadataAccountRequest release];
+ applyMetadataAccountRequest = nil;
+ }
+ [self refreshInfo];
+ } else if ([request isEqualTo:refreshMetadataAccountRequest]) {
+ self.pithosAccount = [refreshMetadataAccountRequest account];
+ @synchronized(self) {
+ [refreshMetadataAccountRequest release];
+ refreshMetadataAccountRequest = nil;
+ }
+ }
}
-- (NSArray *)children {
- if (childrenDirty) {
- @synchronized (self) {
- if (!refreshing) {
- refreshing = YES;
- childrenDirty = NO;
- ASIPithosAccountRequest *accountRequest = [ASIPithosAccountRequest listContainersRequestWithLimit:0
- marker:nil
- shared:NO
- until:nil];
- accountRequest.delegate = self;
- accountRequest.downloadCache = [ASIDownloadCache sharedCache];
- [accountRequest startAsynchronous];
- }
+- (void)accountMetadataRequestFailed:(ASIPithosAccountRequest *)request {
+ if ([request isEqualTo:applyMetadataAccountRequest]) {
+ [PithosUtilities httpRequestErrorAlertWithRequest:applyMetadataAccountRequest];
+ @synchronized(self) {
+ [applyMetadataAccountRequest release];
+ applyMetadataAccountRequest = nil;
+ }
+ } else if ([request isEqualTo:refreshMetadataAccountRequest]) {
+ [PithosUtilities httpRequestErrorAlertWithRequest:refreshMetadataAccountRequest];
+ @synchronized(self) {
+ [refreshMetadataAccountRequest release];
+ refreshMetadataAccountRequest = nil;
}
}
- return children;
}
-- (NSString *)displayName {
- if (displayName == nil) {
- displayName = [[NSString alloc] initWithString:@"account"];
+#pragma mark -
+#pragma mark Info
+
+- (void)applyInfo {
+ @synchronized(self) {
+ if (applyMetadataAccountRequest == nil) {
+ NSMutableDictionary *groups = pithosAccount.groups;
+ if ([groups count] == 0)
+ groups = [NSMutableDictionary dictionaryWithObject:@"" forKey:@"group"];
+ applyMetadataAccountRequest = [[ASIPithosAccountRequest updateAccountMetadataRequestWithGroups:groups
+ metadata:pithosAccount.metadata
+ update:NO] retain];
+ applyMetadataAccountRequest.delegate = self;
+ applyMetadataAccountRequest.didFinishSelector = @selector(accountMetadataRequestFinished:);
+ applyMetadataAccountRequest.didFailSelector = @selector(accountMetadataRequestFailed:);
+ [[PithosUtilities prepareRequest:applyMetadataAccountRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
+ }
}
- return displayName;
}
-- (NSImage *)icon {
- return nil;
+- (void)refreshInfo {
+ @synchronized(self) {
+ if (refreshMetadataAccountRequest == nil) {
+ refreshMetadataAccountRequest = [[ASIPithosAccountRequest accountMetadataRequest] retain];
+ refreshMetadataAccountRequest.delegate = self;
+ refreshMetadataAccountRequest.didFinishSelector = @selector(accountMetadataRequestFinished:);
+ refreshMetadataAccountRequest.didFailSelector = @selector(accountMetadataRequestFailed:);
+ refreshMetadataAccountRequest.downloadCache = [ASIDownloadCache sharedCache];
+ [[PithosUtilities prepareRequest:refreshMetadataAccountRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
+ }
+ }
}
-
+
@end