Use user catalog displayname when displaying modified by
[pithos-macos] / pithos-macos / PithosObjectNode.m
1 //
2 //  PithosObjectNode.m
3 //  pithos-macos
4 //
5 // Copyright 2011-2012 GRNET S.A. All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or
8 // without modification, are permitted provided that the following
9 // conditions are met:
10 // 
11 //   1. Redistributions of source code must retain the above
12 //      copyright notice, this list of conditions and the following
13 //      disclaimer.
14 // 
15 //   2. Redistributions in binary form must reproduce the above
16 //      copyright notice, this list of conditions and the following
17 //      disclaimer in the documentation and/or other materials
18 //      provided with the distribution.
19 // 
20 // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21 // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 // 
33 // The views and conclusions contained in the software and
34 // documentation are those of the authors and should not be
35 // interpreted as representing official policies, either expressed
36 // or implied, of GRNET S.A.
37
38 #import "PithosObjectNode.h"
39 #import "ASIPithosRequest.h"
40 #import "ASIPithos.h"
41 #import "ASIPithosObjectRequest.h"
42 #import "ASIPithosContainer.h"
43 #import "ASIPithosObject.h"
44 #import "ASIDownloadCache.h"
45 #import "PithosAccount.h"
46 #import "PithosUtilities.h"
47 #import "PithosObjectNodeInfoController.h"
48
49 @implementation PithosObjectNode
50 @synthesize pithos, pithosContainer, pithosObject, versions;
51 @synthesize isPublic, translatedModifiedBy;
52
53 #pragma mark -
54 #pragma mark Object Lifecycle
55
56 - (id)initWithPithos:(ASIPithos *)aPithos 
57      pithosContainer:(ASIPithosContainer *)aPithosContainer 
58         pithosObject:(ASIPithosObject *)aPithosObject {
59     if ((self = [super init])) {
60         self.pithos = aPithos;
61         self.pithosContainer = aPithosContainer;
62         self.pithosObject = aPithosObject;
63         isLeafItem = YES;
64     }
65     return self;
66 }
67
68 - (void)dealloc {
69     [refreshVersionsObjectRequest clearDelegatesAndCancel];
70     [refreshMetadataObjectRequest clearDelegatesAndCancel];
71     [applyMetadataObjectRequest clearDelegatesAndCancel];
72 }
73
74 #pragma mark -
75 #pragma mark Internal
76
77 - (void)updateModifiedBy {
78     if (!pithosObject.modifiedBy) {
79         self.translatedModifiedBy = nil;
80     } else {
81         if (pithosAccountManager) {
82             NSString *displayname = [pithosAccountManager displaynameForUUID:pithosObject.modifiedBy safe:NO];
83             if (displayname) {
84                 self.translatedModifiedBy = displayname;
85             } else {
86                 [pithosAccountManager updateUserCatalogForForDisplaynames:nil UUIDs:[NSArray arrayWithObject:pithosObject.modifiedBy]];
87                 self.translatedModifiedBy = [pithosAccountManager displaynameForUUID:pithosObject.modifiedBy safe:YES];
88             }
89         } else {
90             self.translatedModifiedBy = [pithosObject.modifiedBy copy];
91         }
92     }
93 }
94
95 #pragma mark -
96 #pragma mark Properties
97
98 - (void)setPithos:(ASIPithos *)aPithos {
99     if (aPithos && ![aPithos isEqualTo:pithos]) {
100         pithos = aPithos;
101         url = nil;
102     }
103 }
104
105 - (NSString *)url {
106     if (url == nil)
107         url = [[NSString alloc] initWithFormat:@"object %@/%@/%@%@", 
108                (sharingAccount ? [pithos storageURLWithAuthUser:sharingAccount] : pithos.storageURL), 
109                pithosContainer.name, 
110                pithosObject.name, 
111                (shared ? @"?shared" : @"")];
112     return url;
113 }
114
115 - (NSArray *)children {
116     return nil;
117 }
118
119 - (NSString *)displayName {
120     if (displayName == nil) {
121         displayName = [pithosObject.name lastPathComponent];
122         if([pithosObject.name hasSuffix:@"/"])
123             displayName = [displayName stringByAppendingString:@"/"];
124     }
125     return [displayName copy];
126 }
127
128 - (void)setDisplayName:(NSString *)aDisplayName {    
129 }
130
131 - (NSImage *)icon {
132     if (icon == nil)
133         icon = [[NSWorkspace sharedWorkspace] iconForFileType:[pithosObject.name pathExtension]];
134     return icon;
135 }
136
137 - (void)setPithosObject:(ASIPithosObject *)aPithosObject {
138     if (![pithosObject isEqualTo:aPithosObject]) {
139         pithosObject = aPithosObject;
140     }
141     [self updateModifiedBy];
142     self.isPublic = (pithosObject.publicURI != nil);
143     // Refresh browser if the object is in my shared and is no longer shared
144     if (shared && !pithosObject.sharing)
145         [[NSNotificationCenter defaultCenter] postNotificationName:@"PithosBrowserRefreshNeeeded" object:self];
146 }
147
148 - (void)setLimitedPithosObject:(ASIPithosObject *)aPithosObject {
149     if (![pithosObject isEqualTo:aPithosObject]) {
150         self.pithosObject.subdir = aPithosObject.subdir;
151         self.pithosObject.name = aPithosObject.name;
152         self.pithosObject.hash = aPithosObject.hash;
153         self.pithosObject.objectHash = aPithosObject.objectHash;
154         self.pithosObject.UUID = aPithosObject.UUID;
155         self.pithosObject.bytes = aPithosObject.bytes;
156         self.pithosObject.contentType = aPithosObject.contentType;
157         self.pithosObject.lastModified = aPithosObject.lastModified;
158         self.pithosObject.version = aPithosObject.version;
159         self.pithosObject.versionTimestamp = aPithosObject.versionTimestamp;
160         self.pithosObject.modifiedBy = aPithosObject.modifiedBy;
161         self.pithosObject.sharedBy = aPithosObject.sharedBy;
162         self.pithosObject.allowedTo = aPithosObject.allowedTo;
163         if (!pithosNodeInfoController) {
164             self.pithosObject.sharing = aPithosObject.sharing;
165             self.pithosObject.publicURI = aPithosObject.publicURI;
166             self.pithosObject = pithosObject;
167         } else {
168             [self updateModifiedBy];
169         }
170     }
171 }
172
173 #pragma mark -
174 #pragma mark ASIHTTPRequestDelegate
175
176 - (void)objectRequestFinished:(ASIPithosObjectRequest *)request {
177     @autoreleasepool {
178         DLog(@"URL: %@", [request url]);
179         DLog(@"cached: %d", [request didUseCachedResponse]);
180         
181         if ([request isEqualTo:applyMetadataObjectRequest]) {
182             int responseStatusCode = applyMetadataObjectRequest.responseStatusCode;
183             if (responseStatusCode != 202)
184                 [PithosUtilities unexpectedResponseStatusAlertWithRequest:applyMetadataObjectRequest];
185             @synchronized(self) {
186                 applyMetadataObjectRequest = nil;
187             }
188             if (responseStatusCode == 202)
189                 [self refreshInfo];
190         } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
191             [[pithosNodeInfoController window] makeFirstResponder:nil];
192             self.pithosObject = [refreshMetadataObjectRequest object];
193             @synchronized(self) {
194                 refreshMetadataObjectRequest = nil;
195             }
196         } else if ([request isEqualTo:refreshVersionsObjectRequest]) {
197             [[pithosNodeInfoController window] makeFirstResponder:nil];
198             self.versions = [refreshVersionsObjectRequest versions];
199             @synchronized(self) {
200                 refreshVersionsObjectRequest = nil;
201             }
202         }
203     }
204 }
205
206 - (void)objectRequestFailed:(ASIPithosObjectRequest *)request {
207     @autoreleasepool {
208         NSUInteger retries = [[request.userInfo objectForKey:@"retries"] unsignedIntegerValue];
209         if (retries > 0) {
210             ASIPithosObjectRequest *newRequest = (ASIPithosObjectRequest *)[PithosUtilities copyRequest:request];
211             [(NSMutableDictionary *)(newRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
212             if ([request isEqualTo:applyMetadataObjectRequest]) {
213                 @synchronized(self) {
214                     applyMetadataObjectRequest = newRequest;
215                 }
216             } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
217                 @synchronized(self) {
218                     refreshMetadataObjectRequest = newRequest;
219                 }
220             } else if ([request isEqualTo:refreshVersionsObjectRequest]) {
221                 @synchronized(self) {
222                     refreshVersionsObjectRequest = newRequest;
223                 }
224             }
225             [[PithosUtilities prepareRequest:newRequest priority:[[newRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous];
226         } else {
227             if ([request isEqualTo:applyMetadataObjectRequest]) {
228                 [PithosUtilities httpRequestErrorAlertWithRequest:applyMetadataObjectRequest];
229                 @synchronized(self) {
230                     applyMetadataObjectRequest = nil;
231                 }
232             } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
233                 [PithosUtilities httpRequestErrorAlertWithRequest:refreshMetadataObjectRequest];
234                 @synchronized(self) {
235                     refreshMetadataObjectRequest = nil;
236                 }
237             } else if ([request isEqualTo:refreshVersionsObjectRequest]) {
238                 [PithosUtilities httpRequestErrorAlertWithRequest:refreshVersionsObjectRequest];
239                 @synchronized(self) {
240                     refreshVersionsObjectRequest = nil;
241                 }
242             }
243         }
244     }
245 }
246
247 #pragma mark -
248 #pragma mark Info
249
250 - (void)applyInfo {
251     @synchronized(self) {
252         if (applyMetadataObjectRequest == nil) {
253             [[pithosNodeInfoController window] makeFirstResponder:nil];
254             if (sharingAccount) {
255                 applyMetadataObjectRequest = [ASIPithosObjectRequest updateObjectMetadataRequestWithPithos:pithos 
256                                                                                               containerName:pithosContainer.name 
257                                                                                                  objectName:pithosObject.name 
258                                                                                             contentEncoding:nil 
259                                                                                          contentDisposition:nil 
260                                                                                                    manifest:nil 
261                                                                                                     sharing:nil
262                                                                                                    isPublic:(isPublic ? ASIPithosObjectRequestPublicTrue : ASIPithosObjectRequestPublicFalse) 
263                                                                                                    metadata:pithosObject.metadata
264                                                                                                      update:NO];
265                 [applyMetadataObjectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos];
266             } else {
267                 applyMetadataObjectRequest = [ASIPithosObjectRequest updateObjectMetadataRequestWithPithos:pithos 
268                                                                                               containerName:pithosContainer.name 
269                                                                                                  objectName:pithosObject.name 
270                                                                                             contentEncoding:pithosObject.contentEncoding 
271                                                                                          contentDisposition:pithosObject.contentDisposition 
272                                                                                                    manifest:pithosObject.manifest 
273                                                                                                     sharing:(pithosObject.sharing ? pithosObject.sharing : @"")
274                                                                                                    isPublic:(isPublic ? ASIPithosObjectRequestPublicTrue : ASIPithosObjectRequestPublicFalse) 
275                                                                                                    metadata:pithosObject.metadata
276                                                                                                      update:NO];
277             }
278             applyMetadataObjectRequest.delegate = self;
279             applyMetadataObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
280             applyMetadataObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
281             applyMetadataObjectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
282                                                    [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
283                                                    [NSNumber numberWithUnsignedInteger:10], @"retries", 
284                                                    NSStringFromSelector(@selector(objectRequestFinished:)), @"didFinishSelector", 
285                                                    NSStringFromSelector(@selector(objectRequestFailed:)), @"didFailSelector", 
286                                                    nil];
287             [[PithosUtilities prepareRequest:applyMetadataObjectRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
288         }
289     }
290 }
291
292 - (void)refreshInfo {
293     @synchronized(self) {
294         if (refreshMetadataObjectRequest == nil) {
295             refreshMetadataObjectRequest = [ASIPithosObjectRequest objectMetadataRequestWithPithos:pithos 
296                                                                                       containerName:pithosContainer.name 
297                                                                                          objectName:pithosObject.name];
298             if (sharingAccount)
299                 [refreshMetadataObjectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos];
300             refreshMetadataObjectRequest.delegate = self;
301             refreshMetadataObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
302             refreshMetadataObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
303             refreshMetadataObjectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
304                                                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
305                                                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
306                                                      NSStringFromSelector(@selector(objectRequestFinished:)), @"didFinishSelector", 
307                                                      NSStringFromSelector(@selector(objectRequestFailed:)), @"didFailSelector", 
308                                                      nil];
309             if (!sharingAccount)
310                 refreshMetadataObjectRequest.downloadCache = [ASIDownloadCache sharedCache];
311             [[PithosUtilities prepareRequest:refreshMetadataObjectRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
312         }
313     }
314     [self refreshVersions];
315 }
316
317 #pragma mark -
318 #pragma mark Versions
319
320 - (void)refreshVersions {
321     @synchronized(self) {
322         if (refreshVersionsObjectRequest == nil) {
323             refreshVersionsObjectRequest = [ASIPithosObjectRequest objectVersionsRequestWithPithos:pithos 
324                                                                                       containerName:pithosContainer.name 
325                                                                                          objectName:pithosObject.name];
326             if (sharingAccount)
327                 [refreshVersionsObjectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos];
328             refreshVersionsObjectRequest.delegate = self;
329             refreshVersionsObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
330             refreshVersionsObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
331             refreshVersionsObjectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
332                                                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
333                                                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
334                                                      NSStringFromSelector(@selector(objectRequestFinished:)), @"didFinishSelector", 
335                                                      NSStringFromSelector(@selector(objectRequestFailed:)), @"didFailSelector", 
336                                                      nil];
337             if (!sharingAccount)
338                 refreshVersionsObjectRequest.downloadCache = [ASIDownloadCache sharedCache];
339             [[PithosUtilities prepareRequest:refreshVersionsObjectRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
340         }
341     }
342 }
343
344 #pragma mark -
345 #pragma mark Actions
346
347 - (void)showPithosNodeInfo:(id)sender {
348     if (!pithosNodeInfoController) {
349         pithosNodeInfoController = [[PithosObjectNodeInfoController alloc] initWithPithosNode:self];
350         [self refreshInfo];
351     }
352     [pithosNodeInfoController showWindow:sender];
353     [[pithosNodeInfoController window] makeKeyAndOrderFront:sender];
354     [NSApp activateIgnoringOtherApps:YES];
355 }
356
357 @end