source: branches/CoreData/SapphireFrappliance/MetaData/Support/SapphireMovieDirectory.m @ 902

Revision 902, 8.6 KB checked in by gbooker, 5 years ago (diff)

Fixes a random case where an exception was thrown stating "The left hand side for an ALL or ANY operator must be either an NSArray or an NSSet." Apparently, in the predicate syntax, nil.tomanyrelationship does not return an empty set, thereby having a left hand that's not an array or set.

This exception was NOT thrown if one entered the movies virtual directory first. The only method by which I could reliably reproduce this was to restart Finder, enter the collections, frontrow's movies dir, play and audio file, then go to the movies virtual directory.

Line 
1/*
2 * SapphireMovieDirectory.m
3 * Sapphire
4 *
5 * Created by Graham Booker on May 27, 2008.
6 * Copyright 2008 Sapphire Development Team and/or www.nanopi.net
7 * All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License as published by the Free Software Foundation; either version 3 of the License,
11 * or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
14 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 * Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with this program; if not,
18 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 */
20
21#import <SapphireCompatClasses/SapphireFrontRowCompat.h>
22
23#import "SapphireMovieDirectory.h"
24#import "SapphireEntityDirectory.h"
25#import "SapphireFilteredFileDirectory.h"
26#import "CoreDataSupportFunctions.h"
27#import "SapphireBasicDirectoryFunctionsImports.h"
28#import "SapphireFileSorter.h"
29
30#import "SapphireMovie.h"
31#import "SapphireCast.h"
32#import "SapphireDirector.h"
33#import "SapphireGenre.h"
34
35NSArray *multiMovieEntityFetch(NSString *name, NSString *keyFromMovie, NSManagedObjectContext *moc, NSPredicate *filterPredicate)
36{
37        NSPredicate *entPred = nil;
38        if(filterPredicate != nil)
39        {
40                NSPredicate *fetchPredicate = [NSPredicate predicateWithFormat:@"movie != nil"];
41                NSPredicate *finalPred;
42                if(filterPredicate == nil)
43                        finalPred = fetchPredicate;
44                else
45                        finalPred = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:filterPredicate, fetchPredicate, nil]];
46                NSArray *files = doFetchRequest(SapphireFileMetaDataName, moc, finalPred);
47                NSSet *movieIds = [NSSet setWithArray:[files valueForKeyPath:@"movie.objectID"]];
48               
49                if([SapphireFrontRowCompat usingLeopard])
50                {
51                        /*      Damn you Apple for not making take 2 Leopard.  Not only does this make obj C 2 not available,
52                         but it also means that I have to content with a crippled and slower core data.  The else block here
53                         executes on Leopard at several times the speed, but on Tiger throws the exception:
54                         "to-many key not allowed here" even though it can be done through a JOIN in the SQL!!!!!*/
55                        NSPredicate *moviePred = [NSPredicate predicateWithFormat:@"SELF IN %@", movieIds];
56                        NSArray *movies = doFetchRequest(SapphireMovieName, moc, moviePred);
57                        NSArray *entSet = [movies valueForKeyPath:[NSString stringWithFormat:@"@distinctUnionOfSets.%@.objectID", keyFromMovie]];
58                       
59                        entPred = [NSPredicate predicateWithFormat:@"SELF IN %@", entSet];
60                }
61                else
62                        entPred = [NSPredicate predicateWithFormat:@"ANY movies IN %@", movieIds];             
63        }
64        return doFetchRequest(name, moc, entPred);
65}
66
67NSArray *castEntityFetch(NSManagedObjectContext *moc, NSPredicate *filterPredicate)
68{
69        return multiMovieEntityFetch(SapphireCastName, @"cast", moc, filterPredicate);
70}
71
72NSArray *directorEntityFetch(NSManagedObjectContext *moc, NSPredicate *filterPredicate)
73{
74        return multiMovieEntityFetch(SapphireDirectorName, @"directors", moc, filterPredicate);
75}
76
77NSArray *genreEntityFetch(NSManagedObjectContext *moc, NSPredicate *filterPredicate)
78{
79        return multiMovieEntityFetch(SapphireGenreName, @"genres", moc, filterPredicate);
80}
81
82@implementation SapphireMovieDirectory
83
84- (id)initWithContext:(NSManagedObjectContext *)context
85{
86        self = [super init];
87        if(self == nil)
88                return self;
89       
90        moc = [context retain];
91
92        NSPredicate *allPred = [NSPredicate predicateWithFormat:@"movie != nil"];
93        SapphireFilteredFileDirectory *all = [[SapphireFilteredFileDirectory alloc] initWithPredicate:allPred Context:moc];
94        SapphireEntityDirectory *cast = [[SapphireEntityDirectory alloc] initWithEntityFetch:castEntityFetch inContext:moc];
95        SapphireEntityDirectory *director = [[SapphireEntityDirectory alloc] initWithEntityFetch:directorEntityFetch inContext:moc];
96        SapphireEntityDirectory *genre = [[SapphireEntityDirectory alloc] initWithEntityFetch:genreEntityFetch inContext:moc];
97        NSPredicate *top250Pred = [NSPredicate predicateWithFormat:@"movie.imdbTop250Ranking != 0"];
98        SapphireFilteredFileDirectory *top250 = [[SapphireFilteredFileDirectory alloc] initWithPredicate:top250Pred Context:moc];
99        NSPredicate *oscarPred = [NSPredicate predicateWithFormat:@"movie.oscarsWon != 0"];
100        SapphireFilteredFileDirectory *oscar = [[SapphireFilteredFileDirectory alloc] initWithPredicate:oscarPred Context:moc];
101       
102        subDirs = [[NSArray alloc] initWithObjects:
103                           all,
104                           cast,
105                           director,
106                           genre,
107                           top250,
108                           oscar,
109                           nil];
110        names = [[NSArray alloc] initWithObjects:
111                           BRLocalizedString( @"All Movies", @"Select all movies" ),
112                           BRLocalizedString( @"By Cast", @"Select movies based on cast members" ),
113                           BRLocalizedString( @"By Director", @"Select movies based on director" ),
114                           BRLocalizedString( @"By Genre", @"Select movies based on genre" ),
115                           BRLocalizedString( @"IMDB Top 250", @"Show movies in IMDb Top 250 only" ),
116                           BRLocalizedString( @"Academy Award Winning", @"Show Oscar winning movies only" ),
117                           nil];
118       
119        SapphireFileSorter *titleSort = [SapphireMovieTitleSorter sharedInstance];
120        SapphireFileSorter *imdbRankSort = [SapphireMovieIMDBTop250RankSorter sharedInstance];
121        SapphireFileSorter *awardSort = [SapphireMovieAcademyAwardSorter sharedInstance];
122        SapphireFileSorter *dateSort = [SapphireDateSorter sharedInstance];
123        SapphireFileSorter *imdbRatingSort = [SapphireMovieIMDBRatingSorter sharedInstance];
124       
125        NSString *moviePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"video_H" ofType:@"png"];
126       
127        [all setPath:VIRTUAL_DIR_ALL_PATH];
128        [all setCoverArtPath:moviePath];
129        [all setFileSorters:[NSArray arrayWithObjects:titleSort, dateSort, imdbRatingSort, nil]];
130        [cast setPath:VIRTUAL_DIR_CAST_PATH];
131        [cast setCoverArtPath:moviePath];
132        [cast setMetaFileFetchPredicate:[NSPredicate predicateWithFormat:@"movie != nil AND ANY movie.#cast != nil"]];
133        [director setPath:VIRTUAL_DIR_DIRECTOR_PATH];
134        [director setCoverArtPath:moviePath];
135        [director setMetaFileFetchPredicate:[NSPredicate predicateWithFormat:@"movie != nil AND ANY movie.directors != nil"]];
136        [genre setPath:VIRTUAL_DIR_GENRE_PATH];
137        [genre setCoverArtPath:moviePath];
138        [genre setMetaFileFetchPredicate:[NSPredicate predicateWithFormat:@"movie != nil AND ANY movie.genres != nil"]];
139        [top250 setPath:VIRTUAL_DIR_TOP250_PATH];
140        [top250 setCoverArtPath:moviePath];
141        [top250 setFileSorters:[NSArray arrayWithObjects:imdbRankSort, titleSort, dateSort, imdbRatingSort, nil]];
142        [oscar setPath:VIRTUAL_DIR_OSCAR_PATH];
143        [oscar setCoverArtPath:[[NSBundle bundleForClass:[self class]] pathForResource:@"AMPAS_Oscar_H" ofType:@"png"]];
144        [oscar setFileSorters:[NSArray arrayWithObjects:awardSort, titleSort, dateSort, imdbRatingSort, nil]];
145        [subDirs makeObjectsPerformSelector:@selector(setNotificationName:) withObject:MOVIE_DID_CHANGE_PREDICATE_MATCHING];
146        Basic_Directory_Function_Inits
147
148        [all release];
149        [cast release];
150        [director release];
151        [genre release];
152        [top250 release];
153        [oscar release];
154        return self;
155}
156
157- (void) dealloc
158{
159        [subDirs release];
160        [names release];
161        Basic_Directory_Function_Deallocs
162        [super dealloc];
163}
164
165- (NSArray *)files
166{
167        return [NSArray array];
168}
169
170- (NSArray *)directories
171{
172        if(filterPredicate == nil)
173                return names;
174       
175        NSMutableArray *ret = [NSMutableArray array];
176        int i, count = [names count];
177        for(i=0; i<count; i++)
178        {
179                if([[subDirs objectAtIndex:i] containsFileMatchingFilterPredicate:filterPredicate])
180                        [ret addObject:[names objectAtIndex:i]];
181        }
182        return ret;
183}
184
185- (NSArray *)metaFiles
186{
187        NSPredicate *allPred = [NSPredicate predicateWithFormat:@"movie != nil"];
188        return doFetchRequest(SapphireFileMetaDataName, moc, allPred);
189}
190
191- (NSPredicate *)metaFileFetchPredicate
192{
193        return nil;
194}
195
196- (SapphireFileMetaData *)metaDataForFile:(NSString *)file
197{
198        return nil;
199}
200
201- (id <SapphireDirectory>)metaDataForDirectory:(NSString *)directory
202{
203        int index = [names indexOfObject:directory];
204        if(index == NSNotFound)
205                return nil;
206        return [subDirs objectAtIndex:index];
207}
208
209- (void)reloadDirectoryContents
210{
211        [subDirs makeObjectsPerformSelector:@selector(setFilterPredicate:) withObject:filterPredicate];
212        [delegate directoryContentsChanged];
213}
214
215- (NSManagedObjectContext *)managedObjectContext
216{
217        return moc;
218}
219
220- (BOOL)isDeleted
221{
222        return NO;
223}
224
225- (NSString *)path
226{
227        return @"@MOVIES";
228}
229
230- (NSString *)coverArtPath
231{
232        return [[SapphireMetaDataSupport collectionArtPath] stringByAppendingPathComponent:@"@MOVIES"];
233}
234
235- (void)faultAllObjects
236{
237}
238
239- (id <SapphireDirectory>)parentDirectory
240{
241        return nil;
242}
243
244#include "SapphireBasicDirectoryFunctions.h"
245
246@end
Note: See TracBrowser for help on using the repository browser.