header, schmeader
[adiumx.git] / Source / AILogToGroup.m
blobb9d20bc37d41120249e97ac9abfc34dd467fa86e
1 /* 
2  * Adium is the legal property of its developers, whose names are listed in the copyright file included
3  * with this source distribution.
4  * 
5  * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6  * General Public License as published by the Free Software Foundation; either version 2 of the License,
7  * or (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
11  * Public License for more details.
12  * 
13  * You should have received a copy of the GNU General Public License along with this program; if not,
14  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
15  */
17 #import "AILoggerPlugin.h"
18 #import "AILogToGroup.h"
19 #import "AIChatLog.h"
20 #import <AIUtilities/AIFileManagerAdditions.h>
22 @interface AILogToGroup (PRIVATE)
23 - (NSDictionary *)logDict;
24 - (AIChatLog *)_logAtRelativeLogPath:(NSString *)relativeLogPath fileName:(NSString *)fileName;
25 @end
27 @implementation AILogToGroup
29 //A group of logs to an specific user
30 - (id)initWithPath:(NSString *)inPath from:(NSString *)inFrom to:(NSString *)inTo serviceClass:(NSString *)inServiceClass
32     if ((self = [super init]))
33         {
34                 path = [inPath retain];
35                 from = [inFrom retain];
36                 to = [inTo retain];
37                 serviceClass = [inServiceClass retain];
38                 logDict = nil;
39                 partialLogDict = nil;
40                 
41                 defaultManager = [[NSFileManager defaultManager] retain];
42         }
44     return self;
47 //Dealloc
48 - (void)dealloc
50     [path release];
51     [to release];
52     [from release];
53     [serviceClass release];
54         [logDict release];
55         [partialLogDict release];
56         
57         [defaultManager release];
58         
59     [super dealloc];
62 - (NSString *)from
64         return from;
68 - (NSString *)to
70     return to;
73 - (NSString *)path
75         return path;
78 - (NSString *)serviceClass
80         return serviceClass;
83 //Returns an enumerator for all of our logs
84 - (NSEnumerator *)logEnumerator
86         return [[self logDict] objectEnumerator];
88 - (int)logCount
90         return [[self logDict] count];
93 - (NSDictionary *)logDict
95         @synchronized(self) {
96                 if (!logDict) {
97                         NSEnumerator    *enumerator;
98                         NSString                *fileName;
99                         NSString                *logBasePath, *fullPath;
100                         
101                         //
102                         logDict = [[NSMutableDictionary alloc] init];
103                         
104                         //Retrieve any logs we've already loaded
105                         if (partialLogDict) {
106                                 [logDict addEntriesFromDictionary:partialLogDict];
107                                 [partialLogDict release]; partialLogDict = nil;
108                         }
109                         
110                         logBasePath = [AILoggerPlugin logBasePath];
111                         fullPath = [logBasePath stringByAppendingPathComponent:path];
112                         enumerator = [[defaultManager directoryContentsAtPath:fullPath] objectEnumerator];
113                         while ((fileName = [enumerator nextObject])) {                  
114                                 if (![fileName hasPrefix:@"."]) {
115                                         NSString        *relativeLogPath = [path stringByAppendingPathComponent:fileName];
116                                         BOOL            isDir;
117                                         
118                                         if (![logDict objectForKey:relativeLogPath] &&
119                                                 ([defaultManager fileExistsAtPath:[logBasePath stringByAppendingPathComponent:relativeLogPath] isDirectory:&isDir] &&
120                                                  !isDir)) {
121                                                 AIChatLog       *theLog;
122                                                 
123                                                 theLog = [[AIChatLog alloc] initWithPath:relativeLogPath
124                                                                                                                         from:from
125                                                                                                                           to:to
126                                                                                                         serviceClass:serviceClass];
127                                                 if (theLog) {
128                                                         [logDict setObject:theLog
129                                                                                 forKey:relativeLogPath];
130                                                 } else {
131                                                         AILog(@"Class %@: Couldn't make for %@ %@ %@ %@",NSStringFromClass([AIChatLog class]),relativeLogPath,from,to,serviceClass);
132                                                 }       
133                                                 [theLog release];
134                                         }
135                                 }
136                         }
137                 }
138         }
139         
140     return logDict;
144  * @brief Get an AIChatLog within this AILogToGroup
146  * @param inPath A _relative_ path of the form SERVICE.ACCOUNT_NAME/TO_NAME/LogName.Extension
148  * @result The AIChatLog, from the cache if possible
149  */
150 - (AIChatLog *)logAtPath:(NSString *)inPath
152         AIChatLog       *theLog;
154         @synchronized(self) {
155                 if (logDict) {
156                         //Use the full dictionary if we have it
157                         theLog = [logDict objectForKey:inPath];
159                 } else {
160                         //Otherwise, use the partialLog dictionary, adding to it if necessary
161                         if (!partialLogDict) partialLogDict = [[NSMutableDictionary alloc] init];
162                         
163                         if (!(theLog = [partialLogDict objectForKey:inPath])) {                         
164                                 theLog = [[AIChatLog alloc] initWithPath:inPath
165                                                                                                         from:from
166                                                                                                           to:to
167                                                                                         serviceClass:serviceClass];
169                                 [partialLogDict setObject:theLog
170                                                                    forKey:inPath];
171                                 [theLog release];
172                         }
174                         if (!theLog) AILog(@"%@ couldn't find %@ in its partialLogDict",self,inPath);
175                 }
176         }
177         return theLog;
181  * @brief Delete an AIChatLog within this AILogToGroup
183  * @param inPath A _relative_ path of the form SERVICE.ACCOUNT_NAME/TO_NAME/LogName.Extension
184  */
185 - (void)trashLog:(AIChatLog *)aLog
187         NSString *logPath = [[AILoggerPlugin logBasePath] stringByAppendingPathComponent:[aLog path]];
188         [[NSFileManager defaultManager] trashFileAtPath:logPath];
190         //Remove from our dictionaries so we don't reference the removed log
191         [logDict removeObjectForKey:[aLog path]];
192         [partialLogDict removeObjectForKey:[aLog path]];
196  * @brief Partial isEqual implementation
198  * 'Partial' in the sense that it doesn't actually test equality.  If two AILogToGroup objects are for the same service/contact pair,
199  * they are considered equal by this function.  They may (and probably do) have different source accounts and therefore different
200  * contained logs.
202  * This is useful because all To groups for a service/contact pair are presented as a single To group in the Contacts source list.
203  */
204 - (BOOL)isEqual:(id)inObject
206         return ([inObject isMemberOfClass:[self class]] &&
207                         ([[(AILogToGroup *)inObject to] isEqualToString:[self to]] &&
208                          [[(AILogToGroup *)inObject serviceClass] isEqualToString:[self serviceClass]]));
210 - (unsigned)hash
212         return [[self to] hash];
214 @end