Simplify default and support custom notifications for nodes.
[pithos-macos] / pithos-macos / PithosNode.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 "PithosNode.h"
39 #import "PithosNodeInfoController.h"
40 #import "ASIDownloadCache.h"
41 #import "ASIPithosRequest.h"
42
43 @implementation PithosNode
44 @synthesize forcedRefresh, parent, shared, sharingAccount, childrenUpdatedNotificationName, 
45             inheritChildrenUpdatedNotificationName, displayName, isLeafItem, icon;
46 @dynamic url, children, pithos, pithosAccount, pithosContainer, pithosObject;
47
48 #pragma mark -
49 #pragma mark Object Lifecycle
50
51 - (id)init {
52     if ((self = [super init])) {
53         freshness = PithosNodeStateRefreshNeeded;
54         forcedRefresh = NO;
55         shared = NO;
56         isLeafItem = NO;
57         self.childrenUpdatedNotificationName = @"PithosNodeChildrenUpdated";
58         inheritChildrenUpdatedNotificationName = NO;
59     }
60     return self;
61 }
62
63 - (void)dealloc {
64     [pithosNodeInfoController release];
65     [sharingAccount release];
66     [icon release];
67     [displayName release];
68     [childrenUpdatedNotificationName release];
69     [newChildren release];
70     [children release];
71     [url release];
72     [super dealloc];
73 }
74
75 - (BOOL)isEqual:(id)anObject {
76     return ([anObject isKindOfClass:[self class]] && [((PithosNode *)anObject).url isEqual:self.url]);
77 }
78
79 - (NSUInteger)hash {
80     return self.url.hash;
81 }
82
83 #pragma mark -
84 #pragma mark Properties
85
86 - (void)setShared:(BOOL)aShared {
87     if (shared != aShared) {
88         shared = aShared;
89         [url release];
90         url = nil;
91     }
92 }
93
94 - (void)setSharingAccount:(NSString *)aSharingAccount {
95     if (![sharingAccount isEqualToString:aSharingAccount]) {
96         [sharingAccount release];
97         sharingAccount = [aSharingAccount retain];
98         [url release];
99         url = nil;
100     }
101 }
102
103 #pragma mark -
104 #pragma mark Actions
105
106 - (void)invalidateChildren {
107     if (freshness == PithosNodeStateFresh)
108         freshness = PithosNodeStateRefreshNeeded;
109 }
110
111 - (void)invalidateChildrenRecursive {    
112     if (freshness == PithosNodeStateFresh) {
113         for (PithosNode *child in children) {
114             [child invalidateChildrenRecursive];
115         }
116         freshness = PithosNodeStateRefreshNeeded;
117     }
118 }
119
120 - (void)refresh {
121     [self invalidateChildren];
122     self.children;
123 }
124
125 - (void)forceRefresh {
126     forcedRefresh = YES;
127     [self refresh];
128 }
129
130 - (void)postChildrenUpdatedNotificationName {
131     // Notify observers that children are updated
132     if (inheritChildrenUpdatedNotificationName) {
133         PithosNode *ancestor = self;
134         while (ancestor && ancestor.parent) {
135             ancestor = ancestor.parent;
136         }
137         if (ancestor && ancestor.childrenUpdatedNotificationName) {
138             [[NSNotificationCenter defaultCenter] postNotificationName:ancestor.childrenUpdatedNotificationName object:self];
139         }
140     } else if (childrenUpdatedNotificationName) {
141         [[NSNotificationCenter defaultCenter] postNotificationName:childrenUpdatedNotificationName object:self];
142     }
143 }
144
145 - (void)showPithosNodeInfo:(id)sender {
146     // Abstract method
147 }
148
149 - (void)pithosNodeInfoWillClose:(id)sender {
150     if (pithosNodeInfoController) {
151         [pithosNodeInfoController release];
152         pithosNodeInfoController = nil;
153     }
154 }
155
156 - (void)pithosNodeWillBeRemoved {
157     if (pithosNodeInfoController) {
158         pithosNodeInfoController.node = nil;
159         [[pithosNodeInfoController window] close];
160     }
161     for (PithosNode *child in children) {
162         [child pithosNodeWillBeRemoved];
163     }
164 }
165
166 #pragma mark -
167 #pragma mark ASIHTTPRequestDelegate
168
169 - (void)performRequestFinishedDelegateInBackground:(ASIPithosRequest *)request {
170     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
171         [self performSelector:NSSelectorFromString([request.userInfo objectForKey:@"didFinishSelector"]) withObject:request];
172     });
173 }
174
175 - (void)performRequestFailedDelegateInBackground:(ASIPithosRequest *)request {
176     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
177         [self performSelector:NSSelectorFromString([request.userInfo objectForKey:@"didFailSelector"]) withObject:request];
178     });
179 }
180
181 @end