source: branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireDirectoryMetaData.m @ 734

Revision 734, 23.7 KB checked in by gbooker, 6 years ago (diff)

Switched the the next version of the metadata.
Fixes #264

Line 
1#import "SapphireDirectorySymLink.h"
2#import "SapphireFileSymLink.h"
3#import "NSFileManager-Extensions.h"
4#import "CoreDataSupportFunctions.h"
5#import "SapphireMetaDataScanner.h"
6#import "SapphireImportHelper.h"
7#import "NSString-Extensions.h"
8#import "SapphireMetaDataUpgrading.h"
9#import "SapphireBasicDirectoryFunctionsImports.h"
10#import "SapphireEpisode.h"
11#import "SapphireSubEpisode.h"
12#import "SapphireMovie.h"
13#import "NSManagedObject-Extensions.h"
14#import "SapphireCollectionDirectory.h"
15
16@implementation SapphireDirectoryMetaData
17
18+ (SapphireDirectoryMetaData *)directoryWithPath:(NSString *)path inContext:(NSManagedObjectContext *)moc
19{
20        SapphireMetaData *meta = [SapphireMetaData metaDataWithPath:path inContext:moc];
21        if([meta isKindOfClass:[SapphireDirectoryMetaData class]])
22                return (SapphireDirectoryMetaData *)meta;
23        return nil;
24}
25
26+ (SapphireDirectoryMetaData *)internalCreateDirectoryWithPath:(NSString *)path parent:(SapphireDirectoryMetaData *)parent inContext:(NSManagedObjectContext *)moc
27{
28        SapphireDirectoryMetaData *ret = [NSEntityDescription insertNewObjectForEntityForName:SapphireDirectoryMetaDataName inManagedObjectContext:moc];
29        ret.parent = parent;
30        ret.path = path;
31       
32        return ret;
33}
34
35+ (SapphireDirectoryMetaData *)createDirectoryWithPath:(NSString *)path inContext:(NSManagedObjectContext *)moc
36{
37        SapphireDirectoryMetaData *ret = [SapphireDirectoryMetaData directoryWithPath:path inContext:moc];
38        if(ret != nil)
39                return ret;
40       
41        SapphireDirectoryMetaData *parent = [SapphireDirectoryMetaData createDirectoryWithPath:[path stringByDeletingLastPathComponent] inContext:moc];
42        ret = [SapphireDirectoryMetaData internalCreateDirectoryWithPath:path parent:parent inContext:moc];
43       
44        return ret;
45}
46
47+ (SapphireDirectoryMetaData *)createDirectoryWithPath:(NSString *)path parent:(SapphireDirectoryMetaData *)parent inContext:(NSManagedObjectContext *)moc
48{
49        SapphireDirectoryMetaData *ret = [SapphireDirectoryMetaData directoryWithPath:path inContext:moc];
50        if(ret != nil)
51                return ret;
52
53        return [SapphireDirectoryMetaData internalCreateDirectoryWithPath:path parent:parent inContext:moc];
54}
55
56+ (NSDictionary *)upgradeV1DirectoriesFromContext:(NSManagedObjectContext *)oldMoc toContext:(NSManagedObjectContext *)newMoc
57{
58        NSMutableDictionary *lookup = [NSMutableDictionary dictionary];
59        NSArray *dirs = doFetchRequest(SapphireDirectoryMetaDataName, oldMoc, nil);
60        NSEnumerator *dirEnum = [dirs objectEnumerator];
61        NSManagedObjectContext *oldDir;
62        while((oldDir = [dirEnum nextObject]) != nil)
63        {
64                SapphireDirectoryMetaData *newDir = [NSEntityDescription insertNewObjectForEntityForName:SapphireDirectoryMetaDataName inManagedObjectContext:newMoc];
65                NSString *path = [oldDir valueForKey:@"path"];
66                newDir.path = path;
67                NSManagedObject *oldCollection = [newDir valueForKey:@"collectionDirectory"];
68                if(oldCollection != nil)
69                        newDir.collectionDirectory = [SapphireCollectionDirectory upgradeV1CollectionDirectory:oldCollection toContext:newMoc];
70                [lookup setObject:newDir forKey:path];
71        }
72        dirEnum = [dirs objectEnumerator];
73        while((oldDir = [dirEnum nextObject]) != nil)
74        {
75                NSString *path = [oldDir valueForKey:@"path"];
76                NSString *parentPath = [oldDir valueForKeyPath:@"parent.path"];
77                if(parentPath != nil)
78                        ((SapphireDirectoryMetaData *)[lookup objectForKey:path]).parent = [lookup objectForKey:parentPath];
79        }
80        return lookup;
81}
82
83- (id)initWithEntity:(NSEntityDescription *)entity insertIntoManagedObjectContext:(NSManagedObjectContext *)context
84{
85        self = [super initWithEntity:entity insertIntoManagedObjectContext:context];
86        if(self == nil)
87                return self;
88       
89        Basic_Directory_Function_Inits
90       
91        return self;
92}       
93
94- (void) dealloc
95{
96        [importArray release];
97        [cachedLookup release];
98        Basic_Directory_Function_Deallocs
99        [super dealloc];
100}
101
102
103- (void)insertDictionary:(NSDictionary *)dict withDefer:(NSMutableDictionary *)defer andDisplay:(SapphireMetaDataUpgrading *)display
104{
105        NSManagedObjectContext *moc = [self managedObjectContext];
106        NSDictionary *dirs = [dict objectForKey:@"Dirs"];
107        NSArray *allDirs = [[dirs allKeys] sortedArrayUsingSelector:@selector(compare:)];
108        NSEnumerator *dirEnum = [allDirs objectEnumerator];
109        NSString *dir;
110        while((dir = [dirEnum nextObject]) != nil)
111        {
112                NSString *path = [self.path stringByAppendingPathComponent:dir];
113                SapphireDirectoryMetaData *newDir = [SapphireDirectoryMetaData createDirectoryWithPath:path parent:self inContext:moc];
114                [newDir insertDictionary:[dirs objectForKey:dir] withDefer:defer andDisplay:display];
115                if([newDir.metaDirsSet count] == 0 && [newDir.metaFilesSet count] == 0)
116                {
117                        newDir.parent = nil;
118                        [moc deleteObject:newDir];
119                }
120        }
121        NSDictionary *files = [dict objectForKey:@"Files"];
122        NSArray *allFiles = [[files allKeys] sortedArrayUsingSelector:@selector(compare:)];
123        NSEnumerator *fileEnum = [allFiles objectEnumerator];
124        NSString *file;
125        while((file = [fileEnum nextObject]) != nil)
126        {
127                NSString *path = [self.path stringByAppendingPathComponent:file];
128                [display setCurrentFile:[NSString stringByCroppingDirectoryPath:path toLength:3]];
129                SapphireFileMetaData *newFile = [SapphireFileMetaData createFileWithPath:path parent:self inContext:moc];
130                [newFile insertDictionary:[files objectForKey:file] withDefer:defer];
131        }
132}
133
134- (BOOL)checkPredicate:(NSPredicate *)pred duplicateSet:(NSMutableSet *)dups
135{
136        NSManagedObjectContext *moc = [self managedObjectContext];
137        NSPredicate *pathPredicate = [NSPredicate predicateWithFormat:@"path BEGINSWITH %@", [self.path stringByAppendingString:@"/"]];
138        NSPredicate *predicate;
139        if(pred == nil)
140                predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:pathPredicate, filterPredicate, nil]];
141        else
142                predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:pathPredicate, pred, filterPredicate, nil]];
143        if(entityExists(SapphireFileMetaDataName, moc, predicate))
144                return YES;
145       
146        NSArray *array = doFetchRequest(SapphireFileSymLinkName, moc, pathPredicate);
147        if([array count])
148        {
149                NSEnumerator *symEunm = [array objectEnumerator];
150                SapphireFileSymLink *sym;
151                while((sym = [symEunm nextObject]) != nil)
152                {
153                        SapphireFileMetaData *file = sym.file;
154                        //Doing a predicate check is likely faster than these two property fetches and prefix match
155/*                      NSString *finalPath = file.path;
156                        if([finalPath hasPrefix:self.path])
157                                continue;*/
158                        if(pred == nil || [pred evaluateWithObject:file])
159                                return YES;
160                }
161        }
162       
163        array = doFetchRequest(SapphireDirectorySymLinkName, moc, pathPredicate);
164        if([array count])
165        {
166                SapphireDirectorySymLink *sym = nil;
167                NSEnumerator *symEnum = [array objectEnumerator];
168                while((sym = [symEnum nextObject]) != nil)
169                {
170                        SapphireDirectoryMetaData *dir = sym.directory;
171                        NSString *finalPath = dir.path;
172                        if([dups containsObject:finalPath] || [finalPath hasPrefix:self.path])
173                                continue;
174                        [dups addObject:finalPath];
175                        [dir setFilterPredicate:filterPredicate];
176                        if([dir checkPredicate:pred duplicateSet:dups])
177                                return YES;
178                }
179        }
180        return NO;
181}
182
183NSComparisonResult fileAndLinkEpisodeCompare(id file1, id file2, void *context)
184{
185        /*Resolve link and try to sort by episodes*/
186        SapphireFileMetaData *first;
187        if([file1 isKindOfClass:[SapphireFileMetaData class]])
188                first = (SapphireFileMetaData *)file1;
189        else
190                first = ((SapphireFileSymLink *)file1).file;
191
192        SapphireFileMetaData *second;
193        if([file2 isKindOfClass:[SapphireFileMetaData class]])
194                second = (SapphireFileMetaData *)file2;
195        else
196                second = ((SapphireFileSymLink *)file2).file;
197       
198        NSComparisonResult result = [first episodeCompare:second];
199        if(result != NSOrderedSame)
200                return result;
201       
202        result = [first movieCompare:second];
203        if(result != NSOrderedSame)
204                return result;
205       
206        /*Finally sort by path*/
207        return [[[file1 valueForKey:@"path"] lastPathComponent] nameCompare:[[file2 valueForKey:@"path"] lastPathComponent]];
208}
209
210NSComparisonResult dirAndLinkPathCompare(id dir1, id dir2, void *context)
211{
212        return [[[dir1 valueForKey:@"path"] lastPathComponent] nameCompare:[[dir2 valueForKey:@"path"] lastPathComponent]];
213}
214
215- (NSArray *)files
216{
217        return cachedFiles;
218}
219
220- (NSArray *)directories
221{
222        return cachedDirs;
223}
224
225- (id <SapphireDirectory>)metaDataForDirectory:(NSString *)directory
226{
227        SapphireDirectoryMetaData *ret = [cachedLookup objectForKey:directory];
228        if(ret != nil)
229        {
230                if([ret isKindOfClass:[SapphireDirectorySymLink class]])
231                        ret = [(SapphireDirectorySymLink *)ret directory];
232                return ret;
233        }
234        SapphireLog(SAPPHIRE_LOG_GENERAL, SAPPHIRE_LOG_LEVEL_ERROR, @"Somehow couldn't get cache for %@ in %@", directory, self.path);
235        NSString *path = [self.path stringByAppendingPathComponent:directory];
236        NSPredicate *pred = [NSPredicate predicateWithFormat:@"path == %@", path];
237        NSArray *candidates = [[self.metaDirsSet allObjects] filteredArrayUsingPredicate:pred];
238        if([candidates count])
239                ret = [candidates objectAtIndex:0];
240        else
241        {
242                candidates  = [[self.linkedDirsSet allObjects] filteredArrayUsingPredicate:pred];
243                if([candidates count])
244                        ret = ((SapphireDirectorySymLink *)[candidates objectAtIndex:0]).directory;             
245        }
246        [ret setFilterPredicate:filterPredicate];
247       
248        return nil;
249}
250
251- (SapphireFileMetaData *)metaDataForFile:(NSString *)file
252{
253        SapphireFileMetaData *ret = [cachedLookup objectForKey:file];
254        if(ret != nil)
255        {
256                if([ret isKindOfClass:[SapphireFileSymLink class]])
257                        ret = [(SapphireFileSymLink *)ret file];
258                return ret;
259        }
260        NSString *path = [self.path stringByAppendingPathComponent:file];
261        NSPredicate *pred = [NSPredicate predicateWithFormat:@"path == %@", path];
262        NSArray *candidates = [[self.metaFilesSet allObjects] filteredArrayUsingPredicate:pred];
263        if([candidates count])
264                return [candidates objectAtIndex:0];
265       
266        candidates  = [[self.linkedFilesSet allObjects] filteredArrayUsingPredicate:pred];
267        if([candidates count])
268                return ((SapphireFileSymLink *)[candidates objectAtIndex:0]).file;
269       
270        return nil;
271}
272
273- (void)rescanDirWithExistingDirs:(NSMutableArray *)existingDirs files:(NSMutableArray *)existingFiles symDirs:(NSMutableArray *)existingSymDirs symFiles:(NSMutableArray *)existingSymFiles;
274{
275        [importArray release];
276        importArray = [[NSMutableArray alloc] init];
277
278        NSMutableDictionary *dirs = [[NSMutableDictionary alloc] init];
279        NSEnumerator *cachedEnum = [existingDirs objectEnumerator];
280        NSManagedObject *object;
281        while((object = [cachedEnum nextObject]) != nil)
282        {
283                [dirs setObject:object forKey:[object valueForKeyPath:@"path.lastPathComponent"]];
284        }
285       
286        NSMutableDictionary *files = [[NSMutableDictionary alloc] init];
287        cachedEnum = [existingFiles objectEnumerator];
288        while((object = [cachedEnum nextObject]) != nil)
289        {
290                [files setObject:object forKey:[object valueForKeyPath:@"path.lastPathComponent"]];
291        }
292
293        NSMutableDictionary *linkedDirs = [[NSMutableDictionary alloc] init];
294        cachedEnum = [existingSymDirs objectEnumerator];
295        while((object = [cachedEnum nextObject]) != nil)
296        {
297                [linkedDirs setObject:object forKey:[object valueForKeyPath:@"path.lastPathComponent"]];
298        }
299
300        NSMutableDictionary *linkedFiles = [[NSMutableDictionary alloc] init];
301        cachedEnum = [existingSymFiles objectEnumerator];
302        while((object = [cachedEnum nextObject]) != nil)
303        {
304                [linkedFiles setObject:object forKey:[object valueForKeyPath:@"path.lastPathComponent"]];
305        }
306       
307        NSFileManager *fm = [NSFileManager defaultManager];
308        NSManagedObjectContext *moc = [self managedObjectContext];
309       
310        NSArray *names = [fm directoryContentsAtPath:self.path];
311        NSEnumerator *nameEnum = [names objectEnumerator];
312        NSString *name;
313        BOOL modified = NO;     
314        while((name = [nameEnum nextObject]) != nil)
315        {
316                NSString *filePath = [self.path stringByAppendingPathComponent:name];
317                if(![fm acceptFilePath:filePath])
318                        continue;
319               
320                NSDictionary *attributes = [fm fileAttributesAtPath:filePath traverseLink:NO];
321                if([[attributes fileType] isEqualToString:NSFileTypeSymbolicLink])
322                {
323                        /*Sym links are fun*/
324                        NSString *resolvedPath = [filePath stringByResolvingSymlinksInPath];
325                        if(![fm acceptFilePath:resolvedPath])
326                                continue;
327                       
328                        if([fm isDirectory:resolvedPath])
329                        {
330                                if([dirs objectForKey:name] != nil)
331                                {
332                                        //Dir moved, but original data is still here
333                                        SapphireDirectoryMetaData *resolved = [SapphireDirectoryMetaData directoryWithPath:resolvedPath inContext:moc];
334                                        if(resolved != nil)
335                                                [moc deleteObject:resolved];
336                                       
337                                        resolved = (SapphireDirectoryMetaData *)[self metaDataForDirectory:name];
338                                        resolved.parent = [SapphireDirectoryMetaData createDirectoryWithPath:[resolvedPath stringByDeletingLastPathComponent] inContext:moc];
339                                        resolved.path = resolvedPath;
340                                        [dirs removeObjectForKey:name];
341                                }
342                                SapphireDirectorySymLink *newLink = [SapphireDirectorySymLink createDirectoryLinkWithPath:filePath toPath:resolvedPath inContext:moc];
343                                if([linkedDirs objectForKey:name] != nil)
344                                        [linkedDirs removeObjectForKey:name];
345                                else
346                                        [existingSymDirs addObject:newLink];
347                        }
348                        else
349                        {
350                                if([files objectForKey:name] != nil)
351                                {
352                                        //File moved, but original data is still here
353                                        SapphireFileMetaData *resolved = [SapphireFileMetaData fileWithPath:resolvedPath inContext:moc];
354                                        if(resolved != nil)
355                                                [moc deleteObject:resolved];
356                                       
357                                        resolved = [self metaDataForFile:name];
358                                        resolved.parent = [SapphireDirectoryMetaData createDirectoryWithPath:[resolvedPath stringByDeletingLastPathComponent] inContext:moc];
359                                        resolved.path = resolvedPath;
360                                        [files removeObjectForKey:name];
361                                }
362                                SapphireFileSymLink *newLink = [SapphireFileSymLink createFileLinkWithPath:filePath toPath:resolvedPath inContext:moc];
363                                if([linkedFiles objectForKey:name] != nil)
364                                        [linkedFiles removeObjectForKey:name];
365                                else
366                                        [existingSymFiles addObject:newLink];
367                        }
368                        /*      It's not always modified, but rather than figuring out all the cases where it is or isn't
369                         just set it to YES for a rare case and figure it out later if it's an issue*/
370                        modified = YES;
371                }
372                else if([fm isDirectory:filePath])
373                {
374                        SapphireDirectoryMetaData *subDir = [dirs objectForKey:name];
375                        if(subDir == nil)
376                        {
377                                subDir = [SapphireDirectoryMetaData createDirectoryWithPath:filePath parent:self inContext:moc];
378                                [existingDirs addObject:subDir];
379                                modified = YES;
380                        }
381                        else
382                                [dirs removeObjectForKey:name];
383                }
384                else
385                {
386                        SapphireFileMetaData *subFile = [files objectForKey:name];
387                        if(subFile == nil)
388                        {
389                                subFile = [SapphireFileMetaData createFileWithPath:filePath parent:self inContext:moc];
390                                [existingFiles addObject:subFile];
391                                [importArray addObject:subFile];
392                                modified = YES;
393                        }
394                        else
395                        {
396                                [files removeObjectForKey:name];
397                                if([subFile needsUpdating])
398                                        [importArray addObject:subFile];                               
399                        }
400                }
401        }
402       
403        NSEnumerator *objectEnum = [files objectEnumerator];
404        while((object = [objectEnum nextObject]) != nil)
405        {
406                [existingFiles removeObject:object];
407                [moc deleteObject:object];
408                modified = YES;
409        }
410       
411        objectEnum = [dirs objectEnumerator];
412        while((object = [objectEnum nextObject]) != nil)
413        {
414                [existingDirs removeObject:object];
415                [moc deleteObject:object];
416                modified = YES;
417        }
418       
419        objectEnum = [linkedFiles objectEnumerator];
420        while((object = [objectEnum nextObject]) != nil)
421        {
422                [existingSymFiles removeObject:object];
423                [moc deleteObject:object];
424                modified = YES;
425        }
426       
427        objectEnum = [linkedDirs objectEnumerator];
428        while((object = [objectEnum nextObject]) != nil)
429        {
430                [existingSymDirs removeObject:object];
431                [moc deleteObject:object];
432                modified = YES;
433        }
434       
435        if(modified)
436        {
437                [self clearPredicateCache];
438                [SapphireMetaDataSupport save:moc];
439        }
440}
441
442- (void)reloadDirectoryContents
443{
444        NSManagedObjectContext *moc = [self managedObjectContext];
445        [moc refreshObject:self mergeChanges:YES];
446       
447        [cachedLookup release];
448        cachedLookup = [[NSMutableDictionary alloc] init];
449
450        NSPredicate *fetchPred = [NSPredicate predicateWithFormat:@"parent == %@", self];
451        NSMutableArray *fetchedFiles = [doFetchRequest(SapphireFileMetaDataName, moc, fetchPred) mutableCopy];
452        NSMutableArray *fetchedDirs = [doFetchRequest(SapphireDirectoryMetaDataName, moc, fetchPred) mutableCopy];
453        NSMutableArray *linkedFiles = [[self.linkedFilesSet allObjects] mutableCopy];
454        NSMutableArray *linkedDirs = [[self.linkedDirsSet allObjects] mutableCopy];
455       
456        [self rescanDirWithExistingDirs:fetchedDirs files:fetchedFiles symDirs:linkedDirs symFiles:linkedFiles];
457       
458        NSMutableArray *allFiles = [fetchedFiles mutableCopy];
459        [allFiles addObjectsFromArray:linkedFiles];
460        if(filterPredicate != nil)
461                [allFiles filterUsingPredicate:filterPredicate];
462
463        if([allFiles count])
464        {
465                NSMutableSet *files = [NSMutableSet setWithArray:fetchedFiles];
466                [files addObjectsFromArray:[linkedFiles valueForKey:@"file"]];
467                NSSet *allEps = [files valueForKeyPath:@"tvEpisode.objectID"];
468                if([allEps count])
469                {
470                        NSPredicate *fetchPred = [NSPredicate predicateWithFormat:@"SELF IN %@", allEps];
471                        NSArray *episodes = doFetchRequest(SapphireEpisodeName, moc, fetchPred);
472                        if([episodes count])
473                        {
474                                fetchPred = [NSPredicate predicateWithFormat:@"episode IN %@", episodes];
475                                doFetchRequest(SapphireSubEpisodeName, moc, fetchPred);
476                        }
477                }
478                NSSet *allMovies = [files valueForKeyPath:@"movie.objectID"];
479                if([allMovies count])
480                {
481                        NSPredicate *fetchPred = [NSPredicate predicateWithFormat:@"SELF IN %@", allMovies];
482                        doFetchRequest(SapphireMovieName, moc, fetchPred);
483                }
484        }               
485        [allFiles sortUsingFunction:fileAndLinkEpisodeCompare context:nil];
486        [cachedFiles release];
487        cachedFiles = [[NSMutableArray alloc] init];
488        NSEnumerator *objEnum = [allFiles objectEnumerator];
489        SapphireFileMetaData *file;
490        while((file = [objEnum nextObject]) != nil)
491        {
492                NSString *name = [file.path lastPathComponent];
493                [cachedFiles addObject:name];
494                [cachedLookup setObject:file forKey:name];
495        }
496        [allFiles release];
497        [fetchedFiles release];
498        [linkedFiles release];
499       
500        NSMutableArray *allDirs = [fetchedDirs mutableCopy];
501        if(filterPredicate != nil)
502        {
503                int i, count = [allDirs count];
504                for(i=0; i<count; i++)
505                {
506                        SapphireDirectoryMetaData *dir = [allDirs objectAtIndex:i];
507                        if(filterPredicate != [SapphireApplianceController unfilteredPredicate] && ![dir containsFileMatchingFilterPredicate:filterPredicate])
508                        {
509                                [allDirs removeObjectAtIndex:i];
510                                i--;
511                                count--;
512                        }
513                        else
514                        {
515                                [dir setFilterPredicate:filterPredicate];
516                        }
517                }
518        }
519        if(filterPredicate != nil)
520        {
521                int i, count = [linkedDirs count];
522                for(i=0; i<count; i++)
523                {
524                        SapphireDirectorySymLink *link = [linkedDirs objectAtIndex:i];
525                        SapphireDirectoryMetaData *dir = [link directory];
526                        if([dir containsFileMatchingFilterPredicate:filterPredicate])
527                        {
528                                [allDirs addObject:link];
529                                [dir setFilterPredicate:filterPredicate];
530                        }
531                }
532        }
533        else
534                [allDirs addObjectsFromArray:linkedDirs];
535        [allDirs sortUsingFunction:dirAndLinkPathCompare context:nil];
536        [cachedDirs release];
537        cachedDirs = [[NSMutableArray alloc] init];
538        objEnum = [allDirs objectEnumerator];
539        SapphireDirectoryMetaData *dir;
540        while((dir = [objEnum nextObject]) != nil)
541        {
542                NSString *name = [dir.path lastPathComponent];
543                [cachedDirs addObject:name];
544                [cachedLookup setObject:dir forKey:name];
545        }
546        [allDirs release];
547        [fetchedDirs release];
548        [linkedDirs release];
549        [delegate directoryContentsChanged];
550}
551
552- (NSString *)coverArtPathUpToParents:(int)parents
553{
554        NSString *ret = searchCoverArtExtForPath([[self path] stringByAppendingPathComponent:@"Cover Art/cover"]);
555        if(ret != nil)
556                return ret;
557       
558        ret = searchCoverArtExtForPath([[self path] stringByAppendingPathComponent:@"cover"]);
559        if(ret != nil)
560                return ret;
561       
562        if(parents != 0)
563                return [[self parent] coverArtPathUpToParents:parents-1];
564        return nil;
565}
566
567- (NSString *)coverArtPath
568{
569        return [self coverArtPathUpToParents:2];
570}
571
572- (void)invokeOnAllFiles:(NSInvocation *)fileInv
573{
574        NSManagedObjectContext *moc = [self managedObjectContext];
575        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"path BEGINSWITH %@", [self.path stringByAppendingString:@"/"]];
576        if(filterPredicate != nil)
577                predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:predicate, filterPredicate, nil]];
578        NSArray *array = doFetchRequest(SapphireFileMetaDataName, moc, predicate);
579
580        if([array count])
581        {
582                SapphireFileMetaData *file;
583                NSEnumerator *fileEnum = [array objectEnumerator];
584                while((file = [fileEnum nextObject]) != nil)
585                {
586                        [fileInv invokeWithTarget:file];
587                }
588        }
589}
590
591- (BOOL)checkPredicate:(NSPredicate *)pred
592{
593        NSMutableSet *dupSet = [[NSMutableSet alloc] init];
594        BOOL ret = [self checkPredicate:pred duplicateSet:dupSet];
595        [dupSet release];
596        return ret;
597}
598
599- (void)conductScanWithDelegate:(id <SapphireMetaDataScannerDelegate>)subDelegate skipDirectories:(NSMutableSet *)skip andResults:(BOOL)results
600{
601        /*Scan dir and create scanner*/
602        SapphireMetaDataScanner *scanner = [[SapphireMetaDataScanner alloc] initWithDirectoryMetaData:self delegate:subDelegate];
603       
604        NSPredicate *fetchPredicate = [NSPredicate predicateWithFormat:@"path BEGINSWITH %@", [self.path stringByAppendingString:@"/"]];
605        NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"path" ascending:YES];
606        NSManagedObjectContext *moc = [self managedObjectContext];
607        NSArray *dirs = doSortedFetchRequest(SapphireDirectoryMetaDataName, moc, fetchPredicate, sort);
608        NSArray *files = doSortedFetchRequest(SapphireFileMetaDataName, moc, fetchPredicate, sort);
609        NSArray *symDirs = doSortedFetchRequest(SapphireDirectorySymLinkName, moc, fetchPredicate, sort);
610        NSArray *symFiles = doSortedFetchRequest(SapphireFileSymLinkName, moc, fetchPredicate, sort);
611        [sort release];
612       
613        [scanner setSubDirs:dirs files:files symDirs:symDirs symFiles:symFiles];
614       
615        /*Add ourselves to not rescan*/
616        [skip addObject:self.path];
617        [scanner setSkipDirectories:skip];
618        /*We want results*/
619        [scanner setGivesResults:results];
620        [scanner release];
621}
622
623- (void)getSubFileMetasWithDelegate:(id <SapphireMetaDataScannerDelegate>)subDelegate skipDirectories:(NSMutableSet *)skip
624{
625        [self conductScanWithDelegate:subDelegate skipDirectories:skip andResults:YES];
626}
627
628- (void)scanForNewFilesWithDelegate:(id <SapphireMetaDataScannerDelegate>)subDelegate skipDirectories:(NSMutableSet *)skip
629{
630        [self conductScanWithDelegate:subDelegate skipDirectories:skip andResults:NO];
631}
632
633- (void)processNextFile
634{
635        if(![importArray count])
636        {
637                importing &= ~2;
638                return;
639        }
640        SapphireFileMetaData *file = [importArray objectAtIndex:0];
641       
642        /*Get the file and update it*/
643        importing |= 2;
644        [[SapphireImportHelper sharedHelperForContext:[self managedObjectContext]] importAllData:file inform:self];
645}
646
647- (oneway void)informComplete:(BOOL)updated
648{
649        /*Tell delegate we updated*/
650        [SapphireMetaDataSupport save:[self managedObjectContext]];
651        SapphireFileMetaData *file = [importArray objectAtIndex:0];
652        [delegate updateCompleteForFile:[[file path] lastPathComponent]];
653       
654        /*Remove from list and redo timer*/
655        [importArray removeObjectAtIndex:0];
656        if(importing & 1)
657                [self processNextFile];
658        else
659                importing = 0;
660}
661
662- (void)cancelImport
663{
664        importing &= ~1;
665}
666
667- (void)resumeImport
668{
669        importing |= 1;
670        if(!(importing & 2) && ![self isDeleted])
671                [self processNextFile];
672}
673
674- (void)faultAllObjects
675{
676        if([self isFault] || delegate != nil)
677                return;
678        NSManagedObjectContext *moc = [self managedObjectContext];
679        NSEnumerator *objEnum;
680        NSManagedObject *obj;
681       
682        objEnum = [self.metaFilesSet objectEnumerator];
683        while((obj = [objEnum nextObject]) != nil)
684                [obj faultOjbectInContext:moc];
685       
686        objEnum = [self.metaDirsSet objectEnumerator];
687        while((obj = [objEnum nextObject]) != nil)
688                [obj faultOjbectInContext:moc];
689       
690        objEnum = [self.linkedFilesSet objectEnumerator];
691        while((obj = [objEnum nextObject]) != nil)
692        {
693                SapphireFileSymLink *link = (SapphireFileSymLink *)obj;
694                if(![link isFault])
695                {
696                        [link.file faultOjbectInContext:moc];
697                        [link faultOjbectInContext:moc];
698                }
699        }
700       
701        objEnum = [self.linkedDirsSet objectEnumerator];
702        while((obj = [objEnum nextObject]) != nil)
703        {
704                SapphireDirectorySymLink *link = (SapphireDirectorySymLink *)obj;
705                if(![link isFault])
706                {
707                        [link.directory faultOjbectInContext:moc];
708                        [link faultOjbectInContext:moc];
709                }
710        }
711       
712        [self faultOjbectInContext:moc];
713}
714
715- (id <SapphireDirectory>)parentDirectory
716{
717        return self.parent;
718}
719
720#define RECURSIVE_FUNCTIONS_ALREADY_DEFINED
721#include "SapphireBasicDirectoryFunctions.h"
722
723@end
Note: See TracBrowser for help on using the repository browser.