root/branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireEpisode.m @ 840

Revision 840, 11.1 KB (checked in by gbooker, 16 months ago)

Delete unused objects as they become unused so as to not need the prune call later. This will help accelerate things later. Also, handled XML a bit better.

Line 
1#import "SapphireEpisode.h"
2#import "SapphireSeason.h"
3#import "SapphireSubEpisode.h"
4#import "SapphireMediaPreview.h"
5#import "SapphireFileMetaData.h"
6#import "SapphireMetaDataSupport.h"
7#import "SapphireXMLData.h"
8#import "SapphireApplianceController.h"
9#import "CoreDataSupportFunctions.h"
10
11@implementation SapphireEpisode
12
13+ (SapphireEpisode *)episode:(int)ep inSeason:(int)season forShow:(NSString *)show withPath:(NSString *)showPath inContext:(NSManagedObjectContext *)moc
14{
15        SapphireSeason *tvseason = [SapphireSeason season:season forShow:show withPath:showPath inContext:moc];
16        NSEnumerator *epEnum = [tvseason.episodesSet objectEnumerator];
17        SapphireEpisode *tvep;
18        while((tvep = [epEnum nextObject]) != nil)
19        {
20                if([SapphireSubEpisode subEpisode:ep inEpisode:tvep] != nil)
21                        return tvep;
22        }
23       
24        SapphireEpisode *ret = [NSEntityDescription insertNewObjectForEntityForName:SapphireEpisodeName inManagedObjectContext:moc];
25        ret.season = tvseason;
26        ret.tvShow = tvseason.tvShow;
27        [ret addSubEpisodesObject:[SapphireSubEpisode createSubEpisode:ep inEpisode:ret]];
28        return ret;
29}
30
31+ (SapphireEpisode *)episodeTitle:(NSString *)title inSeason:(int)season forShow:(NSString *)show withPath:(NSString *)showPath inContext:(NSManagedObjectContext *)moc
32{
33        SapphireSeason *tvseason = [SapphireSeason season:season forShow:show withPath:showPath inContext:moc];
34        NSEnumerator *epEnum = [tvseason.episodesSet objectEnumerator];
35        SapphireEpisode *tvep;
36        while((tvep = [epEnum nextObject]) != nil)
37        {
38                if([SapphireSubEpisode subEpisodeTitle:title inEpisode:tvep] != nil)
39                        return tvep;
40        }
41       
42        SapphireEpisode *ret = [NSEntityDescription insertNewObjectForEntityForName:SapphireEpisodeName inManagedObjectContext:moc];
43        ret.season = tvseason;
44        ret.tvShow = tvseason.tvShow;
45        [ret addSubEpisodesObject:[SapphireSubEpisode createSubEpisodeTitle:title inEpisode:ret]];
46        return ret;
47}
48
49+ (void)upgradeV1EpisodesFromContext:(NSManagedObjectContext *)oldMoc toContext:(NSManagedObjectContext *)newMoc file:(NSDictionary *)fileLookup
50{
51        NSArray *eps = doFetchRequest(SapphireEpisodeName, oldMoc, nil);
52        NSEnumerator *epEnum = [eps objectEnumerator];
53        NSManagedObject *oldEp;
54        while((oldEp = [epEnum nextObject]) != nil)
55        {
56                NSArray *oldFilePaths = [oldEp valueForKeyPath:@"files.path"];
57                NSEnumerator *pathEnum = [oldFilePaths objectEnumerator];
58                NSString *path;
59                NSMutableSet *newFiles = [NSMutableSet set];
60                while((path = [pathEnum nextObject]) != nil)
61                {
62                        SapphireFileMetaData *newFile = [fileLookup objectForKey:path];
63                        if(newFile != nil)
64                                [newFiles addObject:newFile];
65                }
66                if([newFiles count] == 0)
67                        continue;
68               
69                NSNumber *seasonNum = [oldEp valueForKeyPath:@"season.seasonNumber"];
70                NSString *showName = [oldEp valueForKeyPath:@"tvShow.name"];
71                NSString *showPath = [oldEp valueForKeyPath:@"tvShow.showPath"];
72               
73                SapphireSeason *season = [SapphireSeason season:[seasonNum intValue] forShow:showName withPath:showPath inContext:newMoc];
74                if(season == nil)
75                        continue;
76               
77                SapphireEpisode *newEp = [NSEntityDescription insertNewObjectForEntityForName:SapphireEpisodeName inManagedObjectContext:newMoc];
78                newEp.season = season;
79                newEp.tvShow = season.tvShow;
80                [newEp.filesSet setSet:newFiles];
81               
82                NSEnumerator *subEpEnum = [[oldEp valueForKey:@"subEpisodes"] objectEnumerator];
83                NSManagedObject *subEp;
84                while((subEp = [subEpEnum nextObject]) != nil)
85                        [SapphireSubEpisode upgradeV1SubEpisode:subEp toContext:newMoc inEpisode:newEp];
86        }
87}
88
89- (void) dealloc
90{
91        [sortedSubEpisodes release];
92        [super dealloc];
93}
94
95- (void)createSortedEpisodes
96{
97        if(sortedSubEpisodes != nil)
98                return;
99       
100        NSArray *unsorted = [self.subEpisodesSet allObjects];
101        sortedSubEpisodes = [[unsorted sortedArrayUsingSelector:@selector(compare:)] retain];
102}
103
104- (void)insertDictionary:(NSDictionary *)dict
105{
106        SapphireSubEpisode *sub = [self.subEpisodesSet anyObject];
107        int secondEp = [[dict objectForKey:META_EPISODE_2_NUMBER_KEY] intValue];
108        int setIndex = -1;
109        if(secondEp != 0)
110                setIndex = 0;
111        [sub insertDictionary:dict epIndex:setIndex];
112        if(secondEp != 0)
113        {
114                SapphireSubEpisode *sub = [SapphireSubEpisode createSubEpisode:secondEp inEpisode:self];
115                [sub insertDictionary:dict epIndex:1];
116                [self addSubEpisodesObject:sub];
117        }
118        else
119                [self.subEpisodesSet setSet:[NSSet setWithObject:sub]];
120}
121
122+ (SapphireEpisode *)episodeWithDictionary:(NSDictionary *)dict inContext:(NSManagedObjectContext *)moc
123{
124        NSString *show = [dict objectForKey:META_SHOW_NAME_KEY];
125        int season = [[dict objectForKey:META_SEASON_NUMBER_KEY] intValue];
126        int ep = [[dict objectForKey:META_EPISODE_NUMBER_KEY] intValue];
127       
128        if(show == nil || season == 0)
129                return nil;
130       
131        NSString *showPath = [dict objectForKey:META_SHOW_IDENTIFIER_KEY];
132        SapphireEpisode *ret;
133        if(ep == 0)
134        {
135                NSString *title = [dict objectForKey:META_TITLE_KEY];
136                ret = [SapphireEpisode episodeTitle:title inSeason:season forShow:show withPath:showPath inContext:moc];
137        }
138        else
139                ret = [SapphireEpisode episode:ep inSeason:season forShow:show withPath:showPath inContext:moc];
140        [ret insertDictionary:dict];
141        return ret;
142}
143
144- (NSNumber *)episodeNumber
145{
146        overrideWithXMLForKey(NSNumber, episodeNumber);
147        [self createSortedEpisodes];
148        return ((SapphireSubEpisode *)[sortedSubEpisodes objectAtIndex:0]).episodeNumber;
149}
150
151- (int)episodeNumberValue
152{
153        return [[self episodeNumber] intValue];
154}
155
156- (NSNumber *)lastEpisodeNumber
157{
158        overrideWithXMLForKey(NSNumber, lastEpisodeNumber);
159        if([self.subEpisodesSet count] == 1)
160                //Special case, only one episode here and XML didn't override last ep number
161                return [self episodeNumber];
162        [self createSortedEpisodes];
163        return ((SapphireSubEpisode *)[sortedSubEpisodes objectAtIndex:sortedSubEpisodes.count - 1]).episodeNumber;
164}
165
166- (int)lastEpisodeNumberValue
167{
168        return [[self lastEpisodeNumber] intValue];
169}
170
171- (NSNumber *)absoluteEpisodeNumber
172{
173        overrideWithXMLForKey(NSNumber, absoluteEpisodeNumber);
174        [self createSortedEpisodes];
175        return ((SapphireSubEpisode *)[sortedSubEpisodes objectAtIndex:0]).absoluteEpisodeNumber;
176}
177
178- (int)absoluteEpisodeNumberValue
179{
180        return [[self absoluteEpisodeNumber] intValue];
181}
182
183- (NSString *)episodeTitle
184{
185        overrideWithXMLForKey(NSString, title);
186        [self createSortedEpisodes];
187        NSMutableArray *subs = [[sortedSubEpisodes valueForKey:@"episodeTitle"] mutableCopy];
188        [subs removeObject:[NSNull null]];
189        NSString *ret = [subs componentsJoinedByString:@" / "];
190        [subs release];
191        return ret;
192}
193
194- (NSString *)episodeDescription
195{
196        overrideWithXMLForKey(NSString, contentDescription);
197        [self createSortedEpisodes];
198        NSMutableArray *subs = [[sortedSubEpisodes valueForKey:@"episodeDescription"] mutableCopy];
199        [subs removeObject:[NSNull null]];
200        NSString *ret = [subs componentsJoinedByString:@" / "];
201        [subs release];
202        return ret;
203}
204
205- (NSComparisonResult)compare:(SapphireEpisode *)other
206{
207        NSComparisonResult result = [self.season compare:other.season];
208        if(result != NSOrderedSame)
209                return result;
210       
211        NSNumber *myNumber = [self episodeNumber];
212        NSNumber *theirNumber = [other episodeNumber];
213        if([myNumber intValue] == 0 || [theirNumber intValue] == 0)
214                return [self airDateCompare:other];
215
216        return [myNumber compare:theirNumber];
217}
218
219- (NSDate *)airDate
220{
221        [self createSortedEpisodes];
222        return ((SapphireSubEpisode *)[sortedSubEpisodes objectAtIndex:0]).airDate;
223}
224
225- (NSComparisonResult)airDateCompare:(SapphireEpisode *)other
226{
227        return [[self airDate] compare:[other airDate]];
228}
229
230- (void)insertDisplayMetaData:(NSMutableDictionary *)dict
231{
232        id value = [self episodeTitle];
233        if(value != nil)
234                [dict setObject:value forKey:META_TITLE_KEY];
235        value = [self episodeDescription];
236        if(value != nil)
237                [dict setObject:value forKey:META_DESCRIPTION_KEY];
238        value = [[sortedSubEpisodes objectAtIndex:0] airDate];
239        if(value != nil)
240                [dict setObject:value forKey:META_SHOW_AIR_DATE];
241        int season = [[self season] seasonNumberValue];
242        int ep = [self episodeNumberValue];
243        if(season != 0)
244                [dict setObject:[[self season] seasonNumber] forKey:BRLocalizedString(META_SEASON_NUMBER_KEY, @"Season in metadata display")];
245        if(ep != 0)
246                [dict setObject:[NSNumber numberWithInt:ep] forKey:BRLocalizedString(META_EPISODE_NUMBER_KEY, @"Episode in metadata display")];
247        if(ep != 0 && season != 0)
248        {
249                int lastEp = [self lastEpisodeNumberValue];
250                NSString *key = BRLocalizedString(META_EPISODE_AND_SEASON_KEY, @"Season / Episode in metadata display");
251                if(lastEp != nil && lastEp != ep)
252                        [dict setObject:[NSString stringWithFormat:@"%@ - %d / %d-%d", [[self tvShow] name], season, ep, lastEp] forKey:key];
253                else
254                        [dict setObject:[NSString stringWithFormat:@"%@ - %d / %d", [[self tvShow] name], season, lastEp] forKey:key];         
255        }
256}
257
258- (void)insertAdditionalEpisode:(NSDictionary *)dict
259{
260        SapphireSubEpisode *sub = [SapphireSubEpisode createSubEpisode:[[dict objectForKey:META_EPISODE_NUMBER_KEY] intValue] inEpisode:self];
261        [sub insertDictionary:dict epIndex:-1];
262        [self addSubEpisodesObject:sub];
263}
264
265- (NSString *)path
266{
267        [self createSortedEpisodes];
268        return [[sortedSubEpisodes objectAtIndex:0] path];
269}
270
271- (NSString *)coverArtPath
272{
273        NSString *ret = [[SapphireMetaDataSupport collectionArtPath] stringByAppendingPathComponent:[self path]];
274        NSString *file = searchCoverArtExtForPath(ret);
275        if(file == nil)
276                return [self.season coverArtPath];
277        return ret;
278}
279
280- (NSNumber *)watched
281{
282        NSSet *files = self.filesSet;
283        if([files count] < 2)
284                return [[files anyObject] watched];
285       
286        NSArray *remain = [[files allObjects] filteredArrayUsingPredicate:[SapphireApplianceController unwatchedPredicate]];
287        if([remain count])
288                return [NSNumber numberWithBool:YES];
289        return [NSNumber numberWithBool:NO];
290}
291
292- (NSNumber *)favorite
293{
294        NSSet *files = self.filesSet;
295        if([files count] < 2)
296                return [[files anyObject] favorite];
297       
298        NSArray *remain = [[files allObjects] filteredArrayUsingPredicate:[SapphireApplianceController favoritePredicate]];
299        if([remain count])
300                return [NSNumber numberWithBool:YES];
301        return [NSNumber numberWithBool:NO];
302}
303
304/*Overrides*/
305- (void)addSubEpisodes:(NSSet*)value_
306{
307        [sortedSubEpisodes release];
308        sortedSubEpisodes = nil;
309        [super addSubEpisodes:value_];
310}
311
312- (void)removeSubEpisodes:(NSSet*)value_
313{
314        [sortedSubEpisodes release];
315        sortedSubEpisodes = nil;
316        [super removeSubEpisodes:value_];
317}
318
319- (void)addSubEpisodesObject:(SapphireSubEpisode*)value_
320{
321        [sortedSubEpisodes release];
322        sortedSubEpisodes = nil;
323        [super addSubEpisodesObject:value_];
324}
325
326- (void)removeSubEpisodesObject:(SapphireSubEpisode*)value_
327{
328        [sortedSubEpisodes release];
329        sortedSubEpisodes = nil;
330        [super removeSubEpisodesObject:value_]; 
331}
332
333- (void)clearPredicateCache
334{
335        [self.season clearPredicateCache];
336}
337
338- (void)addFiles:(NSSet*)addedFiles
339{
340        [super addFiles:addedFiles];
341        [self clearPredicateCache];
342}
343
344- (BOOL)shouldDelete
345{
346        return [self.filesSet count] == 0;
347}
348
349-(void)removeFiles:(NSSet*)removeFiles
350{
351        [super removeFiles:removeFiles];
352        if([self.filesSet count] == 0)
353                [SapphireMetaDataSupport setObjectForPendingDelete:self];
354        else
355                [self clearPredicateCache];
356}
357
358- (void)addFilesObject:(SapphireFileMetaData *)addedFile
359{
360        [super addFilesObject:addedFile];
361        [self clearPredicateCache];
362}
363
364- (void)removeFilesObject:(SapphireFileMetaData *)removeFile
365{
366        [super removeFilesObject:removeFile];
367        if([self.filesSet count] == 0)
368                [SapphireMetaDataSupport setObjectForPendingDelete:self];
369        else
370                [self clearPredicateCache];
371}
372
373@end
Note: See TracBrowser for help on using the browser.