Initial commit of pithos-macos.
[pithos-macos] / pithos-macos / PithosContainer.m
1 //
2 //  PithosNode.m
3 //  pithos-macos
4 //
5 // Copyright 2011 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 "PithosContainer.h"
39 #import "PithosObject.h"
40 #import "PithosSubdir.h"
41 #import "ASIPithosContainerRequest.h"
42 #import "ASIPithosObject.h"
43 #import "ASIDownloadCache.h"
44
45 static NSImage *icon = nil;
46
47 @implementation PithosContainer
48 @synthesize containerName;
49
50 + (void)initialize {
51         if (self == [PithosContainer class])
52         icon = [[NSImage imageNamed:@"container"] retain];
53 }
54
55 #pragma mark -
56 #pragma mark Object Lifecycle
57
58 - (id)initWithContainerName:(NSString *)aContainerName {
59     if ((self = [super init])) {
60         containerName = [aContainerName copy];
61         refreshing = NO;
62         prefix = nil;
63     }
64     return self;
65 }
66
67 - (void)dealloc {
68     [prefix release];
69     [objects release];
70     [containerName release];
71     [super dealloc];
72 }
73
74 #pragma mark -
75 #pragma mark ASIHTTPRequestDelegate
76
77 - (void)requestFinished:(ASIPithosContainerRequest *)containerRequest {
78     NSLog(@"URL: %@", [containerRequest url]);
79     NSLog(@"cached: %d", [containerRequest didUseCachedResponse]);
80
81     NSArray *someObjects = [containerRequest objects];
82     if (objects == nil) {
83         objects = [[NSMutableArray alloc] initWithArray:someObjects];
84     } else {
85         [objects addObjectsFromArray:someObjects];
86     }
87     if ([someObjects count] < 10000) {
88         if (!containerRequest.didUseCachedResponse || ([objects count] != [someObjects count]) || !children) {
89             // Save new children
90             NSLog(@"using newChildren");
91             NSMutableArray *newChildren = [NSMutableArray array];
92             for (ASIPithosObject *object in objects) {
93                 if (object.subdir) {
94                     PithosSubdir *node = [[[PithosSubdir alloc] initWithContainerName:containerName subdirName:object.name] autorelease];
95                     if (children) {
96                         NSUInteger oldIndex = [children indexOfObject:node];
97                         if (oldIndex != NSNotFound)
98                             // Use the same pointer value, if possible
99                             node = [children objectAtIndex:oldIndex];
100                     }
101                     [newChildren addObject:node];                
102                 } else {
103                     PithosObject *node = [[[PithosObject alloc] initWithContainerName:containerName objectName:object.name] autorelease];
104                     if (children) {
105                         NSUInteger oldIndex = [children indexOfObject:node];
106                         if (oldIndex != NSNotFound)
107                             // Use the same pointer value, if possible
108                             node = [children objectAtIndex:oldIndex];
109                     }
110                     [newChildren addObject:node];                                
111                 }
112             }
113             [children release];
114             children = [newChildren retain];
115         }
116         // Else cache was used and all results were fetched during this request, so previousChildren can be reused
117         [objects release];
118         objects = nil;
119         // XXX sort then based on preferences
120         refreshing = NO;
121         // Notify observers that children are updated
122         [[NSNotificationCenter defaultCenter] postNotificationName:@"PithosNodeChildrenUpdated" object:self];
123     } else {
124         // Do an additional request to fetch more objects
125         ASIPithosContainerRequest *newContainerRequest = [ASIPithosContainerRequest listObjectsRequestWithContainerName:containerName 
126                                                                                                                   limit:0 
127                                                                                                                  marker:[[someObjects lastObject] name] 
128                                                                                                                  prefix:prefix 
129                                                                                                               delimiter:@"/" 
130                                                                                                                    path:nil 
131                                                                                                                    meta:nil 
132                                                                                                                  shared:NO 
133                                                                                                                   until:nil];
134         newContainerRequest.delegate = self;
135         newContainerRequest.downloadCache = [ASIDownloadCache sharedCache];
136         [newContainerRequest startAsynchronous];
137     }
138 }
139
140 - (void)requestFailed:(ASIPithosContainerRequest *)containerRequest {
141     // XXX do something on error, cleanup
142     NSLog(@"error:%@", [containerRequest error]);
143     [objects release];
144     objects = nil;
145     childrenDirty = YES;
146     refreshing = NO;
147 }
148
149 #pragma mark -
150 #pragma mark Properties
151
152 - (NSString *)url {
153     if (url == nil) 
154         url = [[NSString alloc] initWithFormat:@"%@/%@", [ASIPithosRequest storageURL], containerName];
155     return url;
156 }
157
158 - (NSArray *)children {
159     if (childrenDirty) {
160         @synchronized (self) {
161             if (!refreshing) {
162                 refreshing = YES;
163                 childrenDirty = NO;
164                 ASIPithosContainerRequest *containerRequest = [ASIPithosContainerRequest listObjectsRequestWithContainerName:containerName 
165                                                                                                                        limit:0 
166                                                                                                                       marker:nil 
167                                                                                                                       prefix:prefix 
168                                                                                                                    delimiter:@"/" 
169                                                                                                                         path:nil 
170                                                                                                                         meta:nil 
171                                                                                                                       shared:NO 
172                                                                                                                        until:nil];
173                 containerRequest.delegate = self;
174                 containerRequest.downloadCache = [ASIDownloadCache sharedCache];
175                 [containerRequest startAsynchronous];
176             }
177         }
178     }
179     return children;
180 }
181
182 - (NSString *)displayName {
183     return [[containerName copy] autorelease];
184 }
185
186 - (NSImage *)icon {
187     return icon;
188 }
189
190 @end