Support changes in container and object metadata.
[pithos-macos] / pithos-macos / PithosObjectNode.m
index 490881e..6217018 100644 (file)
@@ -1,8 +1,8 @@
 //
-//  PithosNode.m
+//  PithosObjectNode.m
 //  pithos-macos
 //
-// Copyright 2011 GRNET S.A. All rights reserved.
+// Copyright 2011-2012 GRNET S.A. All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or
 // without modification, are permitted provided that the following
 
 #import "PithosObjectNode.h"
 #import "ASIPithosRequest.h"
+#import "ASIPithos.h"
+#import "ASIPithosObjectRequest.h"
+#import "ASIPithosContainer.h"
+#import "ASIPithosObject.h"
+#import "ASIDownloadCache.h"
+#import "PithosUtilities.h"
+#import "PithosObjectNodeInfoController.h"
 
 @implementation PithosObjectNode
+@synthesize pithos, pithosContainer, pithosObject;
+@synthesize isPublic;
 
 #pragma mark -
 #pragma mark Object Lifecycle
 
-- (id)initWithPithosContainer:(ASIPithosContainer *)aPithosContainer pithosObject:(ASIPithosObject *)aPithosObject {
+- (id)initWithPithos:(ASIPithos *)aPithos 
+     pithosContainer:(ASIPithosContainer *)aPithosContainer 
+        pithosObject:(ASIPithosObject *)aPithosObject {
     if ((self = [super init])) {
-        pithosContainer = [aPithosContainer retain];
-        pithosObject = [aPithosObject retain];
+        self.pithos = aPithos;
+        self.pithosContainer = aPithosContainer;
+        self.pithosObject = aPithosObject;
         isLeafItem = YES;
     }
     return self;
 }
 
 - (void)dealloc {
-    [icon release];
+    [refreshMetadataObjectRequest clearDelegatesAndCancel];
+    [refreshMetadataObjectRequest release];
+    [applyMetadataObjectRequest clearDelegatesAndCancel];
+    [applyMetadataObjectRequest release];
     [pithosObject release];
     [pithosContainer release];
+    [pithos release];
     [super dealloc];
 }
 
 #pragma mark -
 #pragma mark Properties
 
+- (void)setPithos:(ASIPithos *)aPithos {
+    if (aPithos && ![aPithos isEqualTo:pithos]) {
+        [pithos release];
+        pithos = [aPithos retain];
+        [url release];
+        url = nil;
+    }
+}
+
 - (NSString *)url {
-    if (url == nil) 
-        url = [[NSString alloc] initWithFormat:@"object %@/%@/%@", [ASIPithosRequest storageURL], pithosContainer.name, pithosObject.name];
+    if (url == nil)
+        url = [[NSString alloc] initWithFormat:@"object %@/%@/%@%@", 
+               (sharingAccount ? [pithos storageURLWithAuthUser:sharingAccount] : pithos.storageURL), 
+               pithosContainer.name, 
+               pithosObject.name, 
+               (shared ? @"?shared" : @"")];
     return url;
 }
 
     return [[displayName copy] autorelease];
 }
 
+- (void)setDisplayName:(NSString *)aDisplayName {    
+}
+
 - (NSImage *)icon {
-    if (icon == nil) {
+    if (icon == nil)
         icon = [[[NSWorkspace sharedWorkspace] iconForFileType:[pithosObject.name pathExtension]] retain];
-    }
     return icon;
 }
 
-- (NSString *)kind {
-    return pithosObject.contentType;
+- (void)setPithosObject:(ASIPithosObject *)aPithosObject {
+    if (![pithosObject isEqualTo:aPithosObject]) {
+        [pithosObject release];
+        pithosObject = [aPithosObject retain];
+    }
+    self.isPublic = (pithosObject.publicURI != nil);
+    // Refresh browser if the object is in my shared and is no longer shared
+    if (shared && !pithosObject.sharing)
+        [[NSNotificationCenter defaultCenter] postNotificationName:@"PithosBrowserRefreshNeeeded" object:self];
 }
 
-- (NSString *)size {
-    return [NSString stringWithFormat:@"%lu B", pithosObject.bytes];
+- (void)setLimitedPithosObject:(ASIPithosObject *)aPithosObject {
+    if (![pithosObject isEqualTo:aPithosObject]) {
+        self.pithosObject.subdir = aPithosObject.subdir;
+        self.pithosObject.name = aPithosObject.name;
+        self.pithosObject.hash = aPithosObject.hash;
+        self.pithosObject.objectHash = aPithosObject.objectHash;
+        self.pithosObject.UUID = aPithosObject.UUID;
+        self.pithosObject.bytes = aPithosObject.bytes;
+        self.pithosObject.contentType = aPithosObject.contentType;
+        self.pithosObject.lastModified = aPithosObject.lastModified;
+        self.pithosObject.version = aPithosObject.version;
+        self.pithosObject.versionTimestamp = aPithosObject.versionTimestamp;
+        self.pithosObject.modifiedBy = aPithosObject.modifiedBy;
+        self.pithosObject.sharedBy = aPithosObject.sharedBy;
+        self.pithosObject.allowedTo = aPithosObject.allowedTo;
+        if (!pithosNodeInfoController) {
+            self.pithosObject.sharing = aPithosObject.sharing;
+            self.pithosObject.publicURI = aPithosObject.publicURI;
+            self.pithosObject = pithosObject;
+        }
+    }
 }
 
-- (NSString *)modified {
-    return [NSDateFormatter localizedStringFromDate:pithosObject.lastModified 
-                                          dateStyle:NSDateFormatterShortStyle 
-                                          timeStyle:NSDateFormatterShortStyle];
+#pragma mark -
+#pragma mark ASIHTTPRequestDelegate
+
+- (void)objectRequestFinished:(ASIPithosObjectRequest *)request {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    NSLog(@"URL: %@", [request url]);
+    NSLog(@"cached: %d", [request didUseCachedResponse]);
+    
+    if ([request isEqualTo:applyMetadataObjectRequest]) {
+        int responseStatusCode = applyMetadataObjectRequest.responseStatusCode;
+        if (responseStatusCode != 202)
+            [PithosUtilities unexpectedResponseStatusAlertWithRequest:applyMetadataObjectRequest];
+        @synchronized(self) {
+            [applyMetadataObjectRequest release];
+            applyMetadataObjectRequest = nil;
+        }
+        if (responseStatusCode == 202)
+            [self refreshInfo];
+    } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
+        [[pithosNodeInfoController window] makeFirstResponder:nil];
+        self.pithosObject = [refreshMetadataObjectRequest object];
+        @synchronized(self) {
+            [refreshMetadataObjectRequest release];
+            refreshMetadataObjectRequest = nil;
+        }
+    }
+    [pool drain];
 }
 
-- (NSString *)modifiedBy {
-    return pithosObject.modifiedBy;
+- (void)objectRequestFailed:(ASIPithosObjectRequest *)request {
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    NSUInteger retries = [[request.userInfo objectForKey:@"retries"] unsignedIntegerValue];
+    if (retries > 0) {
+        ASIPithosObjectRequest *newRequest = (ASIPithosObjectRequest *)[PithosUtilities copyRequest:request];
+        [(NSMutableDictionary *)(newRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
+        if ([request isEqualTo:applyMetadataObjectRequest]) {
+            @synchronized(self) {
+                [applyMetadataObjectRequest release];
+                applyMetadataObjectRequest = newRequest;
+            }
+        } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
+            @synchronized(self) {
+                [refreshMetadataObjectRequest release];
+                refreshMetadataObjectRequest = newRequest;
+            }
+        }
+        [[PithosUtilities prepareRequest:newRequest priority:[[newRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous];
+    } else {
+        if ([request isEqualTo:applyMetadataObjectRequest]) {
+            dispatch_async(dispatch_get_main_queue(), ^{
+                [PithosUtilities httpRequestErrorAlertWithRequest:applyMetadataObjectRequest];
+            });
+            @synchronized(self) {
+                [applyMetadataObjectRequest release];
+                applyMetadataObjectRequest = nil;
+            }
+        } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
+            dispatch_async(dispatch_get_main_queue(), ^{
+                [PithosUtilities httpRequestErrorAlertWithRequest:refreshMetadataObjectRequest];
+            });
+            @synchronized(self) {
+                [refreshMetadataObjectRequest release];
+                refreshMetadataObjectRequest = nil;
+            }
+        }
+    }
+    [pool drain];
+}
+
+#pragma mark -
+#pragma mark Info
+
+- (void)applyInfo {
+    @synchronized(self) {
+        if (applyMetadataObjectRequest == nil) {
+            [[pithosNodeInfoController window] makeFirstResponder:nil];
+            if (sharingAccount) {
+                applyMetadataObjectRequest = [[ASIPithosObjectRequest updateObjectMetadataRequestWithPithos:pithos 
+                                                                                              containerName:pithosContainer.name 
+                                                                                                 objectName:pithosObject.name 
+                                                                                            contentEncoding:nil 
+                                                                                         contentDisposition:nil 
+                                                                                                   manifest:nil 
+                                                                                                    sharing:nil
+                                                                                                   isPublic:(isPublic ? ASIPithosObjectRequestPublicTrue : ASIPithosObjectRequestPublicFalse) 
+                                                                                                   metadata:pithosObject.metadata
+                                                                                                     update:NO] retain];
+                [applyMetadataObjectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos];
+            } else {
+                applyMetadataObjectRequest = [[ASIPithosObjectRequest updateObjectMetadataRequestWithPithos:pithos 
+                                                                                              containerName:pithosContainer.name 
+                                                                                                 objectName:pithosObject.name 
+                                                                                            contentEncoding:pithosObject.contentEncoding 
+                                                                                         contentDisposition:pithosObject.contentDisposition 
+                                                                                                   manifest:pithosObject.manifest 
+                                                                                                    sharing:(pithosObject.sharing ? pithosObject.sharing : @"")
+                                                                                                   isPublic:(isPublic ? ASIPithosObjectRequestPublicTrue : ASIPithosObjectRequestPublicFalse) 
+                                                                                                   metadata:pithosObject.metadata
+                                                                                                     update:NO] retain];
+            }
+            applyMetadataObjectRequest.delegate = self;
+            applyMetadataObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+            applyMetadataObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
+            applyMetadataObjectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+                                                   [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
+                                                   [NSNumber numberWithUnsignedInteger:10], @"retries", 
+                                                   NSStringFromSelector(@selector(objectRequestFinished:)), @"didFinishSelector", 
+                                                   NSStringFromSelector(@selector(objectRequestFailed:)), @"didFailSelector", 
+                                                   nil];
+            [[PithosUtilities prepareRequest:applyMetadataObjectRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
+        }
+    }
 }
 
-- (NSString *)version {
-    return pithosObject.version;
+- (void)refreshInfo {
+    @synchronized(self) {
+        if (refreshMetadataObjectRequest == nil) {
+            refreshMetadataObjectRequest = [[ASIPithosObjectRequest objectMetadataRequestWithPithos:pithos 
+                                                                                      containerName:pithosContainer.name 
+                                                                                         objectName:pithosObject.name] retain];
+            if (sharingAccount)
+                [refreshMetadataObjectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos];
+            refreshMetadataObjectRequest.delegate = self;
+            refreshMetadataObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+            refreshMetadataObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
+            refreshMetadataObjectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+                                                     [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
+                                                     [NSNumber numberWithUnsignedInteger:10], @"retries", 
+                                                     NSStringFromSelector(@selector(objectRequestFinished:)), @"didFinishSelector", 
+                                                     NSStringFromSelector(@selector(objectRequestFailed:)), @"didFailSelector", 
+                                                     nil];
+            refreshMetadataObjectRequest.downloadCache = [ASIDownloadCache sharedCache];
+            [[PithosUtilities prepareRequest:refreshMetadataObjectRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
+        }
+    }
+}
+
+#pragma mark -
+#pragma mark Actions
+
+- (void)showPithosNodeInfo:(id)sender {
+    if (!pithosNodeInfoController) {
+        pithosNodeInfoController = [[PithosObjectNodeInfoController alloc] initWithPithosNode:self];
+        [self refreshInfo];
+    }
+    [pithosNodeInfoController showWindow:sender];
+    [[pithosNodeInfoController window] makeKeyAndOrderFront:sender];
+    [NSApp activateIgnoringOtherApps:YES];
 }
 
 @end