root / Classes / Folder.m @ f474d3f4
History | View | Annotate | Download (10.2 kB)
1 |
// |
---|---|
2 |
// Folder.m |
3 |
// OpenStack |
4 |
// |
5 |
// Created by Mike Mayo on 12/7/10. |
6 |
// The OpenStack project is provided under the Apache 2.0 license. |
7 |
// |
8 |
|
9 |
#import "Folder.h" |
10 |
#import "StorageObject.h" |
11 |
#import "NSObject+NSCoding.h" |
12 |
#import "PithosUtilities.h" |
13 |
|
14 |
@implementation Folder |
15 |
|
16 |
@synthesize folderObject, parent, objects, folders, objectsAndFoldersCount; |
17 |
@synthesize name, sharing, contentType, lastModifiedString, metadata; |
18 |
@synthesize sortedContentsByName, sortedContentsByDate; |
19 |
|
20 |
#pragma mark - Object lifecycle |
21 |
|
22 |
- (id)initWithObject:(StorageObject *)anObject { |
23 |
if ((self = [super init])) { |
24 |
self.folderObject = anObject; |
25 |
self.objects = [NSMutableDictionary dictionary]; |
26 |
self.folders = [NSMutableDictionary dictionary]; |
27 |
} |
28 |
return self; |
29 |
} |
30 |
|
31 |
- (id)init { |
32 |
StorageObject *anObject = [[[StorageObject alloc] init] autorelease]; |
33 |
return [self initWithObject:anObject]; |
34 |
} |
35 |
|
36 |
+ (id)folderWithObject:(StorageObject *)anObject { |
37 |
return [[[self alloc] initWithObject:anObject] autorelease]; |
38 |
} |
39 |
|
40 |
+ (id)folder { |
41 |
return [[[self alloc] init] autorelease]; |
42 |
} |
43 |
|
44 |
- (NSComparisonResult)compareByName:(id)item { |
45 |
return [self.name caseInsensitiveCompare:[item name]]; |
46 |
} |
47 |
|
48 |
- (NSComparisonResult)compareByDate:(id)item { |
49 |
return [self.lastModifiedString caseInsensitiveCompare:[item lastModifiedString]]; |
50 |
} |
51 |
|
52 |
#pragma mark - Serialization |
53 |
|
54 |
- (id)initWithCoder:(NSCoder *)coder { |
55 |
if ((self = [super init])) { |
56 |
[self autoDecode:coder]; |
57 |
} |
58 |
return self; |
59 |
} |
60 |
|
61 |
- (void)encodeWithCoder:(NSCoder *)coder { |
62 |
[self autoEncodeWithCoder:coder]; |
63 |
} |
64 |
|
65 |
#pragma mark - Memory management |
66 |
|
67 |
-(void)dealloc { |
68 |
[folderObject release]; |
69 |
[parent release]; |
70 |
[folders release]; |
71 |
[objects release]; |
72 |
[sortedContentsByName release]; |
73 |
[sortedContentsByDate release]; |
74 |
[super dealloc]; |
75 |
} |
76 |
|
77 |
#pragma mark - Properties |
78 |
|
79 |
- (void)setName:(NSString *)aName { |
80 |
self.folderObject.name = aName; |
81 |
} |
82 |
|
83 |
- (NSString *)name { |
84 |
return self.folderObject.name; |
85 |
} |
86 |
|
87 |
- (void)setSharing:(NSString *)aSharing { |
88 |
self.folderObject.sharing = aSharing; |
89 |
} |
90 |
|
91 |
- (NSString *)sharing { |
92 |
return self.folderObject.sharing; |
93 |
} |
94 |
|
95 |
- (void)setContentType:(NSString *)aContentType { |
96 |
self.folderObject.contentType = aContentType; |
97 |
} |
98 |
|
99 |
- (NSString *)contentType { |
100 |
return self.folderObject.contentType; |
101 |
} |
102 |
|
103 |
- (void)setMetadata:(NSMutableDictionary *)aMetadata { |
104 |
self.folderObject.metadata = aMetadata; |
105 |
} |
106 |
|
107 |
- (NSMutableDictionary *)metadata { |
108 |
return self.folderObject.metadata; |
109 |
} |
110 |
|
111 |
- (void)setLastModifiedString:(NSString *)aLastModifiedString { |
112 |
self.folderObject.lastModifiedString = aLastModifiedString; |
113 |
} |
114 |
|
115 |
- (NSString *)lastModifiedString { |
116 |
return self.folderObject.lastModifiedString; |
117 |
} |
118 |
|
119 |
- (void)setObjects:(NSMutableDictionary *)objs { |
120 |
if (![objects isEqualToDictionary:objs]) { |
121 |
[objects release]; |
122 |
NSMutableDictionary *folderedFiles = [NSMutableDictionary dictionary]; |
123 |
NSMutableDictionary *files = [NSMutableDictionary dictionary]; |
124 |
self.folders = [[NSMutableDictionary alloc] init]; |
125 |
|
126 |
for (NSString *key in objs) { |
127 |
StorageObject *object = [objs objectForKey:key]; |
128 |
BOOL objectHasTrailingSlash = NO; |
129 |
if ([object.name hasSuffix:@"/"]) { |
130 |
objectHasTrailingSlash = YES; |
131 |
object.name = [object.name substringToIndex:(object.name.length - 1)]; |
132 |
} |
133 |
|
134 |
NSRange slashRange = [object.name rangeOfString:@"/"]; |
135 |
if (slashRange.location != NSNotFound) { |
136 |
// build up the folder structure |
137 |
NSString *folderName = [object.name substringToIndex:slashRange.location]; |
138 |
object.name = [object.name substringFromIndex:(slashRange.location + 1)]; |
139 |
if (objectHasTrailingSlash) |
140 |
object.name = [object.name stringByAppendingString:@"/"]; |
141 |
|
142 |
if (![folderedFiles objectForKey:folderName]) { |
143 |
[folderedFiles setObject:[NSMutableDictionary dictionary] forKey:folderName]; |
144 |
} |
145 |
|
146 |
NSMutableDictionary *folderFiles = [folderedFiles objectForKey:folderName]; |
147 |
[folderFiles setObject:object forKey:object.name]; |
148 |
} else if ([PithosUtilities isContentTypeDirectory:object.contentType]) { |
149 |
Folder *folder = [Folder folderWithObject:object]; |
150 |
if (objectHasTrailingSlash) |
151 |
folder.name = [folder.name stringByAppendingString:@"/"]; |
152 |
folder.parent = self; |
153 |
[self.folders setObject:folder forKey:folder.name]; |
154 |
} else { |
155 |
// put the files in this folder |
156 |
if (objectHasTrailingSlash) |
157 |
object.name = [object.name stringByAppendingString:@"/"]; |
158 |
[files setObject:object forKey:object.name]; |
159 |
} |
160 |
} |
161 |
|
162 |
// take the foldered files and recursively build the rest of the folder structure |
163 |
for (NSString *folderName in [folderedFiles allKeys]) { |
164 |
Folder *folder; |
165 |
StorageObject *object = [objs objectForKey:folderName]; |
166 |
if (object && [PithosUtilities isContentTypeDirectory:object.contentType]) { |
167 |
folder = [Folder folderWithObject:object]; |
168 |
} else { |
169 |
folder = [Folder folder]; |
170 |
folder.name = folderName; |
171 |
folder.metadata = [NSMutableDictionary dictionary]; |
172 |
} |
173 |
folder.parent = self; |
174 |
folder.objects = [folderedFiles objectForKey:folderName]; |
175 |
[self.folders setObject:folder forKey:folder.name]; |
176 |
} |
177 |
|
178 |
objects = [files retain]; |
179 |
[sortedContentsByName release]; |
180 |
sortedContentsByName = nil; |
181 |
[sortedContentsByDate release]; |
182 |
sortedContentsByDate = nil; |
183 |
} |
184 |
} |
185 |
|
186 |
- (NSArray *)sortedContentsByName { |
187 |
if (!sortedContentsByName) { |
188 |
NSMutableArray *contents = [[NSMutableArray alloc] initWithArray:[self.folders allValues]]; |
189 |
[contents addObjectsFromArray:[self.objects allValues]]; |
190 |
sortedContentsByName = [[NSArray alloc] initWithArray:[contents sortedArrayUsingSelector:@selector(compareByName:)]]; |
191 |
} |
192 |
return sortedContentsByName; |
193 |
} |
194 |
|
195 |
- (NSArray *)sortedContentsByDate { |
196 |
if (!sortedContentsByDate) { |
197 |
NSMutableArray *contents = [[NSMutableArray alloc] initWithArray:[self.folders allValues]]; |
198 |
[contents addObjectsFromArray:[self.objects allValues]]; |
199 |
sortedContentsByDate = [[NSArray alloc] initWithArray:[contents sortedArrayUsingSelector:@selector(compareByDate:)]]; |
200 |
} |
201 |
return sortedContentsByDate; |
202 |
} |
203 |
|
204 |
- (NSUInteger)objectsAndFoldersCount { |
205 |
return (self.objects.count + self.folders.count); |
206 |
} |
207 |
|
208 |
#pragma mark - Actions |
209 |
|
210 |
- (NSArray *)sortedContentsUsingFilter:(NSString *)filter scope:(NSString *)scope |
211 |
sortType:(NSString *)sortType sortDirection:(NSString *)sortDirection { |
212 |
NSArray *sortedContents = nil; |
213 |
if ([sortType isEqualToString:@"date"]) { |
214 |
sortedContents = self.sortedContentsByDate; |
215 |
} else { |
216 |
sortedContents = self.sortedContentsByName; |
217 |
} |
218 |
if ([sortDirection isEqualToString:@"Z-A"]) { |
219 |
sortedContents = [[sortedContents reverseObjectEnumerator] allObjects]; |
220 |
} |
221 |
if (!filter || !filter.length) { |
222 |
return sortedContents; |
223 |
} |
224 |
return [sortedContents objectsAtIndexes: |
225 |
[[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sortedContents.count)] indexesPassingTest:^(NSUInteger idx, BOOL *stop) { |
226 |
id item = [sortedContents objectAtIndex:idx]; |
227 |
if ([scope isEqualToString:@"name"] || [scope isEqualToString:@"all"]) { |
228 |
NSString *itemName = [item name]; |
229 |
if (itemName) { |
230 |
NSUInteger nameLocation = [itemName rangeOfString:filter |
231 |
options:NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch].location; |
232 |
if (nameLocation != NSNotFound) |
233 |
return YES; |
234 |
} |
235 |
} |
236 |
if ([scope isEqualToString:@"date"] || [scope isEqualToString:@"all"]) { |
237 |
NSString *itemDate = [item lastModifiedString]; |
238 |
if (itemDate) { |
239 |
NSUInteger dateLocation = [itemDate rangeOfString:filter |
240 |
options:NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch].location; |
241 |
if (dateLocation != NSNotFound) |
242 |
return YES; |
243 |
} |
244 |
} |
245 |
if ([scope isEqualToString:@"type"] || [scope isEqualToString:@"all"]) { |
246 |
NSString *itemType = [item contentType]; |
247 |
if (itemType) { |
248 |
NSUInteger typeLocation = [itemType rangeOfString:filter |
249 |
options:NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch].location; |
250 |
if (typeLocation != NSNotFound) |
251 |
return YES; |
252 |
} |
253 |
} |
254 |
// Consider searching additional metadata when the scope is all |
255 |
return NO; |
256 |
}]]; |
257 |
} |
258 |
|
259 |
- (NSString *)fullPath { |
260 |
if (self.parent) { |
261 |
return [[self.parent fullPath] stringByAppendingFormat:@"/%@", self.name]; |
262 |
} else if (self.name) { |
263 |
return self.name; |
264 |
} else { |
265 |
return @""; |
266 |
} |
267 |
} |
268 |
|
269 |
- (void)addFolder:(Folder *)aFolder { |
270 |
[self.folders setObject:aFolder forKey:aFolder.name]; |
271 |
[sortedContentsByName release]; |
272 |
sortedContentsByName = nil; |
273 |
[sortedContentsByDate release]; |
274 |
sortedContentsByDate = nil; |
275 |
} |
276 |
|
277 |
- (void)addObject:(StorageObject *)anObject { |
278 |
[self.objects setObject:anObject forKey:anObject.name]; |
279 |
[sortedContentsByName release]; |
280 |
sortedContentsByName = nil; |
281 |
[sortedContentsByDate release]; |
282 |
sortedContentsByDate = nil; |
283 |
} |
284 |
|
285 |
- (void)removeFolder:(Folder *)aFolder { |
286 |
if ([self.folders objectForKey:aFolder.name]) { |
287 |
[self.folders removeObjectForKey:aFolder.name]; |
288 |
[sortedContentsByName release]; |
289 |
sortedContentsByName = nil; |
290 |
[sortedContentsByDate release]; |
291 |
sortedContentsByDate = nil; |
292 |
} |
293 |
} |
294 |
|
295 |
- (void)removeObject:(StorageObject *)anObject { |
296 |
if ([self.objects objectForKey:anObject.name]) { |
297 |
[self.objects removeObjectForKey:anObject.name]; |
298 |
[sortedContentsByName release]; |
299 |
sortedContentsByName = nil; |
300 |
[sortedContentsByDate release]; |
301 |
sortedContentsByDate = nil; |
302 |
} |
303 |
} |
304 |
|
305 |
@end |