All requests made asynchronous.
[pithos-macos] / pithos-macos / PithosAccountNode.m
index e0a3e0f..e45b6d7 100644 (file)
@@ -1,5 +1,5 @@
 //
-//  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
 - (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:(ASIHTTPRequest *)request {
+- (void)accountRequestFinished:(ASIPithosAccountRequest *)request {
     NSLog(@"URL: %@", [accountRequest url]);
     NSLog(@"cached: %d", [accountRequest didUseCachedResponse]);
+
+    self.pithosAccount = [accountRequest account];
     
     NSArray *someContainers = [accountRequest containers];
     if (containers == nil) {
             // Save new children
             NSLog(@"using newChildren");
             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) {
                         // Use the same pointer value, if possible
                         node = [children objectAtIndex:oldIndex];
                         node.pithosContainer = container;
+                        [keptNodes addIndex:oldIndex];
                     }
                 }
                 [newChildren addObject:node];
             }
+            [[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 existing children can be reused
         [accountRequest release];
         accountRequest = nil;
         [containers release];
         containers = nil;
-        // XXX sort children based on preferences
+        forcedRefresh = NO;
         @synchronized(self) {
             freshness = PithosNodeStateRefreshFinished;
         }
         // Do an additional request to fetch more objects
         accountRequest = [[ASIPithosAccountRequest listContainersRequestWithLimit:0 
                                                                            marker:[[someContainers lastObject] name] 
-                                                                           shared:NO 
+                                                                           shared:shared 
                                                                             until:nil] retain];
+        if (sharingAccount)
+            [accountRequest setRequestUserFromDefaultTo:sharingAccount];
         accountRequest.delegate = self;
-        accountRequest.downloadCache = [ASIDownloadCache sharedCache];
-        [accountRequest startAsynchronous];
+        if (!forcedRefresh)
+            accountRequest.downloadCache = [ASIDownloadCache sharedCache];
+        [[PithosUtilities prepareRequest:accountRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous];
     }
 }
 
-- (void)requestFailed:(ASIHTTPRequest *)request {
-    // 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;
+    forcedRefresh = NO;
     @synchronized(self) {
         freshness = PithosNodeStateRefreshNeeded;
     }
 }
 
-#pragma mark -
-#pragma mark Properties
+- (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;
+        }
+    }
+}
 
-- (NSString *)url {
-    if (url == nil) 
-        url = [[ASIPithosRequest storageURL] copy];
-    return url;
+- (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;
+        }
+    }
 }
 
-- (NSArray *)children {
+#pragma mark -
+#pragma mark Info
+
+- (void)applyInfo {
     @synchronized(self) {
-        switch (freshness) {
-            case PithosNodeStateFresh:
-                break;
-            case PithosNodeStateRefreshNeeded:
-                freshness = PithosNodeStateRefreshing;
-                accountRequest = [[ASIPithosAccountRequest listContainersRequestWithLimit:0 
-                                                                                   marker:nil 
-                                                                                   shared:NO 
-                                                                                    until:nil] retain];
-                accountRequest.delegate = self;
-                accountRequest.downloadCache = [ASIDownloadCache sharedCache];
-                [accountRequest startAsynchronous];
-                break;
-            case PithosNodeStateRefreshing:
-                break;
-            case PithosNodeStateRefreshFinished:
-                if (newChildren) {
-                    [children release];
-                    children = newChildren;
-                    newChildren = nil;
-                }
-                freshness = PithosNodeStateFresh;
-            default:
-                break;
+        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 children;
     }
 }
 
-- (NSString *)displayName {
-    if (displayName == nil) {
-        displayName = [[NSString alloc] initWithString:@"account"];
+- (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];
+        }
     }
-    return displayName;
 }
 
-- (NSImage *)icon {
-    return nil;
-}
-    
 @end