Index: /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireSeason.m
===================================================================
--- /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireSeason.m	(revision 734)
+++ /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireSeason.m	(revision 840)
@@ -2,4 +2,5 @@
 #import "SapphireTVShow.h"
 #import "SapphireFileSorter.h"
+#import "SapphireMetaDataSupport.h"
 
 @implementation SapphireSeason
@@ -82,3 +83,22 @@
 }
 
+- (BOOL)shouldDelete
+{
+	return [self.episodesSet count] == 0;
+}
+
+-(void)removeEpisodes:(NSSet*)removedEpisodes
+{
+	[super removeEpisodes:removedEpisodes];
+	if([self.episodesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+}
+
+- (void)removeEpisodesObject:(SapphireEpisode*)removedEpisode
+{
+	[super removeEpisodesObject:removedEpisode];
+	if([self.episodesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+}
+
 @end
Index: /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireCast.m
===================================================================
--- /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireCast.m	(revision 739)
+++ /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireCast.m	(revision 840)
@@ -3,4 +3,5 @@
 #import "CoreDataSupportFunctions.h"
 #import "SapphireFileSorter.h"
+#import "SapphireMetaDataSupport.h"
 
 @implementation SapphireCast
@@ -64,7 +65,6 @@
 }
 
-- (void)removeMoviesObject:(SapphireMovie*)value_
+- (void)checkMajorRole
 {
-	[super removeMoviesObject:value_];
 	BOOL currentMajorRole = self.hasMajorRoleValue;
 	BOOL majorRole = NO;
@@ -83,3 +83,26 @@
 }
 
+- (BOOL)shouldDelete
+{
+	return [self.moviesSet count] == 0;
+}
+
+-(void)removeMovies:(NSSet*)removedMovies
+{
+	[super removeMovies:removedMovies];
+	if([self.moviesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+	else
+		[self checkMajorRole];
+}
+
+- (void)removeMoviesObject:(SapphireMovie *)removedMovie
+{
+	[super removeMoviesObject:removedMovie];
+	if([self.moviesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+	else
+		[self checkMajorRole];
+}
+
 @end
Index: /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireTVShow.m
===================================================================
--- /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireTVShow.m	(revision 734)
+++ /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireTVShow.m	(revision 840)
@@ -128,3 +128,22 @@
 }
 
+- (BOOL)shouldDelete
+{
+	return [self.episodesSet count] == 0;
+}
+
+-(void)removeEpisodes:(NSSet*)removedEpisodes
+{
+	[super removeEpisodes:removedEpisodes];
+	if([self.episodesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+}
+
+- (void)removeEpisodesObject:(SapphireEpisode*)removedEpisode
+{
+	[super removeEpisodesObject:removedEpisode];
+	if([self.episodesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+}
+
 @end
Index: /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireGenre.m
===================================================================
--- /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireGenre.m	(revision 739)
+++ /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireGenre.m	(revision 840)
@@ -3,4 +3,5 @@
 #import "SapphireFileSorter.h"
 #import "SapphireMovie.h"
+#import "SapphireMetaDataSupport.h"
 
 @implementation SapphireGenre
@@ -63,3 +64,22 @@
 }
 
+- (BOOL)shouldDelete
+{
+	return [self.moviesSet count] == 0;
+}
+
+-(void)removeMovies:(NSSet*)removedMovies
+{
+	[super removeMovies:removedMovies];
+	if([self.moviesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+}
+
+- (void)removeMoviesObject:(SapphireMovie *)removedMovie
+{
+	[super removeMoviesObject:removedMovie];
+	if([self.moviesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+}
+
 @end
Index: /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireEpisode.m
===================================================================
--- /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireEpisode.m	(revision 836)
+++ /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireEpisode.m	(revision 840)
@@ -342,8 +342,16 @@
 }
 
+- (BOOL)shouldDelete
+{
+	return [self.filesSet count] == 0;
+}
+
 -(void)removeFiles:(NSSet*)removeFiles
 {
 	[super removeFiles:removeFiles];
-	[self clearPredicateCache];
+	if([self.filesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+	else
+		[self clearPredicateCache];
 }
 
@@ -357,5 +365,8 @@
 {
 	[super removeFilesObject:removeFile];
-	[self clearPredicateCache];
+	if([self.filesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+	else
+		[self clearPredicateCache];
 }
 
Index: /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireDirector.m
===================================================================
--- /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireDirector.m	(revision 739)
+++ /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireDirector.m	(revision 840)
@@ -2,4 +2,5 @@
 #import "CoreDataSupportFunctions.h"
 #import "SapphireFileSorter.h"
+#import "SapphireMetaDataSupport.h"
 
 @implementation SapphireDirector
@@ -62,3 +63,22 @@
 }
 
+- (BOOL)shouldDelete
+{
+	return [self.moviesSet count] == 0;
+}
+
+-(void)removeMovies:(NSSet*)removedMovies
+{
+	[super removeMovies:removedMovies];
+	if([self.moviesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+}
+
+- (void)removeMoviesObject:(SapphireMovie *)removedMovie
+{
+	[super removeMoviesObject:removedMovie];
+	if([self.moviesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+}
+
 @end
Index: /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireMovie.m
===================================================================
--- /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireMovie.m	(revision 836)
+++ /branches/CoreData/SapphireFrappliance/MetaData/SapphireMObjects/SapphireMovie.m	(revision 840)
@@ -271,5 +271,5 @@
 			while((name = [nameEnum nextObject]) != nil)
 			{
-				SapphireCast *aCast = [SapphireCast cast:name inContext:moc];
+				SapphireCast *aCast = [SapphireCast createCast:name inContext:moc];
 				if(aCast != nil)
 					[mutRet addObject:aCast];
@@ -290,5 +290,5 @@
 	NSArray *arc = [ordered valueForKey:@"name"];
 	[self setValue:[NSKeyedArchiver archivedDataWithRootObject:arc] forKey:ORDERED_CAST_DATA];
-	[self.castSet setSet:[NSSet setWithArray:ordered]];
+	[self setValue:[NSSet setWithArray:ordered] forKey:@"cast"];
 	int i, count=[ordered count];
 	if(count > 10)
@@ -319,5 +319,5 @@
 			while((genre = [genreEnum nextObject]) != nil)
 			{
-				SapphireGenre *aGenre = [SapphireGenre genre:genre inContext:moc];
+				SapphireGenre *aGenre = [SapphireGenre createGenre:genre inContext:moc];
 				if(aGenre != nil)
 					[mutRet addObject:aGenre];
@@ -338,5 +338,5 @@
 	NSArray *arc = [ordered valueForKey:@"name"];
 	[self setValue:[NSKeyedArchiver archivedDataWithRootObject:arc] forKey:ORDERED_GENRES_DATA];
-	[self.genresSet addObjectsFromArray:ordered];
+	[self setValue:[NSSet setWithArray:ordered] forKey:@"genres"];
 }
 
@@ -360,5 +360,5 @@
 			while((name = [nameEnum nextObject]) != nil)
 			{
-				SapphireDirector *aDir = [SapphireDirector director:name inContext:moc];
+				SapphireDirector *aDir = [SapphireDirector createDirector:name inContext:moc];
 				if(aDir != nil)
 					[mutRet addObject:aDir];
@@ -379,5 +379,5 @@
 	NSArray *arc = [ordered valueForKey:@"name"];
 	[self setValue:[NSKeyedArchiver archivedDataWithRootObject:arc] forKey:ORDERED_DIRECTOR_DATA];
-	[self.directorsSet addObjectsFromArray:ordered];
+	[self setValue:[NSSet setWithArray:ordered] forKey:@"directors"];
 }
 
@@ -402,5 +402,5 @@
 	}
 	[self setPrimitiveValue:nil forKey:ORDERED_CAST_KEY];
-	[self.castSet setSet:[NSSet setWithArray:self.orderedCast]];
+	[self setValue:[NSSet setWithArray:self.orderedCast] forKey:@"cast"];
 }
 
@@ -417,5 +417,5 @@
 	}
 	[self setPrimitiveValue:nil forKey:ORDERED_GENRES_KEY];
-	[self.genresSet setSet:[NSSet setWithArray:self.orderedGenres]];
+	[self setValue:[NSSet setWithArray:self.orderedGenres] forKey:@"genres"];
 }
 
@@ -432,5 +432,5 @@
 	}
 	[self setPrimitiveValue:nil forKey:ORDERED_DIRECTOR_KEY];
-	[self.directorsSet setSet:[NSSet setWithArray:self.orderedDirectors]];
+	[self setValue:[NSSet setWithArray:self.orderedDirectors] forKey:@"directors"];
 }
 
@@ -451,5 +451,6 @@
 {
 	[super removeXml:removedXMLs];
-	[self checkXMLOverridenSets];
+	//This can occur during a delete propogation, which appears to have KVO completely broken; workaround
+	[SapphireMetaDataSupport setObjectForPendingDelete:self];
 }
 
@@ -463,5 +464,6 @@
 {
 	[super removeXmlObject:removedXML];
-	[self checkXMLOverridenSets];
+	//This can occur during a delete propogation, which appears to have KVO completely broken; workaround
+	[SapphireMetaDataSupport setObjectForPendingDelete:self];
 }
 
@@ -575,8 +577,20 @@
 }
 
+- (BOOL)shouldDelete
+{
+	if([self.filesSet count] == 0)
+		return YES;
+	
+	[self checkXMLOverridenSets];
+	return NO;
+}
+
 -(void)removeFiles:(NSSet*)removeFiles
 {
 	[super removeFiles:removeFiles];
-	[self clearPredicateCache];
+	if([self.filesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+	else
+		[self clearPredicateCache];
 }
 
@@ -590,5 +604,8 @@
 {
 	[super removeFilesObject:removeFile];
-	[self clearPredicateCache];
+	if([self.filesSet count] == 0)
+		[SapphireMetaDataSupport setObjectForPendingDelete:self];
+	else
+		[self clearPredicateCache];
 }
 
Index: /branches/CoreData/SapphireFrappliance/MetaData/Support/SapphireMetaDataSupport.h
===================================================================
--- /branches/CoreData/SapphireFrappliance/MetaData/Support/SapphireMetaDataSupport.h	(revision 820)
+++ /branches/CoreData/SapphireFrappliance/MetaData/Support/SapphireMetaDataSupport.h	(revision 840)
@@ -44,4 +44,14 @@
  */
 + (void)pruneMetaData:(NSManagedObjectContext *)moc;
+
+/*!
+ * @brief Sets an object up for pending delete
+ *
+ * Any object added to this set will be first checked before delete.  The check is calling selector
+ * shouldDelete and if returns YES, performs the delete, otherwise it is removed from set.
+ *
+ * @param objectToDelete The object to delete
+ */
++ (void)setObjectForPendingDelete:(NSManagedObject *)objectToDelete;
 
 /*!
Index: /branches/CoreData/SapphireFrappliance/MetaData/Support/SapphireMetaDataSupport.m
===================================================================
--- /branches/CoreData/SapphireFrappliance/MetaData/Support/SapphireMetaDataSupport.m	(revision 839)
+++ /branches/CoreData/SapphireFrappliance/MetaData/Support/SapphireMetaDataSupport.m	(revision 840)
@@ -40,4 +40,9 @@
 #import "SapphireSeason.h"
 #import "CoreDataSupportFunctions.h"
+
+@interface NSManagedObject (deleteDelegate)
+- (BOOL)shouldDelete;
+@end
+
 
 @interface NSManagedObject (ChangePersistence)
@@ -140,4 +145,5 @@
 
 static NSSet *coverArtExtentions = nil;
+static NSMutableSet *pendingDeleteObjects = nil;
 
 NSString *searchCoverArtExtForPath(NSString *path)
@@ -173,5 +179,6 @@
 						  @"png",
 						  @"gif",
-						  nil];	
+						  nil];
+	pendingDeleteObjects = [[NSMutableSet alloc] init];
 }
 
@@ -258,4 +265,40 @@
 }
 
++ (void)setObjectForPendingDelete:(NSManagedObject *)objectToDelete
+{
+	[pendingDeleteObjects addObject:objectToDelete];
+}
+
+/*!
+ * @brief Deletes pending objects
+ *
+ * Deletes all objects in the pending queue, but calls shouldDelete first to make sure it should
+ * be deleted.  This is also used as a hack to work around CD apparent inability to make KVO
+ * notifications during an object delete when it is within an KVO notification.
+ */
++ (void)deletePendingObjects
+{
+	NSManagedObjectContext *mainMoc = [SapphireMetaDataSupport sharedInstance]->mainMoc;
+	[mainMoc processPendingChanges];		
+	while([pendingDeleteObjects count])
+	{
+		NSManagedObject *obj;
+		NSSet *pendingObjects = [pendingDeleteObjects copy];
+		[pendingDeleteObjects removeAllObjects];
+		NSEnumerator *objEnum = [pendingObjects objectEnumerator];
+		while((obj = [objEnum nextObject]) != nil)
+		{
+			if([obj isDeleted])
+				continue;
+			if([obj managedObjectContext] != mainMoc)
+				continue;
+			if(![obj respondsToSelector:@selector(shouldDelete)] || [obj shouldDelete])
+				[mainMoc deleteObject:obj];
+		}
+		[pendingObjects release];
+		[mainMoc processPendingChanges];		
+	}
+}
+
 - (void)realWriteMetaData:(NSTimer *)timer
 {
@@ -274,4 +317,5 @@
 	BOOL success = NO;
 	@try {
+		[SapphireMetaDataSupport deletePendingObjects];
 		success = [context save:&error];
 	}
Index: /branches/CoreData/SapphireFrappliance/main_debug.m
===================================================================
--- /branches/CoreData/SapphireFrappliance/main_debug.m	(revision 833)
+++ /branches/CoreData/SapphireFrappliance/main_debug.m	(revision 840)
@@ -38,4 +38,9 @@
 #import "SapphireMetaDataSupport.h"
 #import "SapphireAllImporter.h"
+#import "SapphireTVShow.h"
+#import "SapphireGenre.h"
+#import "SapphireCast.h"
+#import "SapphireDirector.h"
+#import "SapphireXMLData.h"
 
 void overrideApplicationSupportdir(NSString *override);
@@ -96,4 +101,9 @@
 @end
 
+@interface SapphireMetaDataSupport (debug)
++ (void)deletePendingObjects;
+@end
+
+
 
 
@@ -112,5 +122,5 @@
 	
 //	overrideApplicationSupportdir([NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Frontrow"]);
-#define TESTING_UPGRADE
+//#define TESTING_UPGRADE
 #ifdef TESTING_UPGRADE
 	{
@@ -198,5 +208,5 @@
 	}
 #endif
-#define TESTING_DIRECTORY_RESCAN
+//#define TESTING_DIRECTORY_RESCAN
 #ifdef TESTING_DIRECTORY_RESCAN
 	{
@@ -209,4 +219,26 @@
 	}
 #endif
+#define TESTING_AUTO_PRUNING
+#ifdef TESTING_AUTO_PRUNING
+	{
+		SapphireFileMetaData *file = [SapphireFileMetaData fileWithPath:@"/Users/gbooker/Movies/MovieTests/Little Einsteins.avi" inContext:moc];
+		SapphireXMLData *xml = [file xmlData];
+		[moc deleteObject:xml];
+		[SapphireMetaDataSupport deletePendingObjects];
+		SapphireDirectoryMetaData *dir = [SapphireDirectoryMetaData directoryWithPath:@"/Users/gbooker/Movies/MovieTests" inContext:moc];
+		[moc deleteObject:dir];
+		[SapphireMetaDataSupport deletePendingObjects];
+		dir = [SapphireDirectoryMetaData directoryWithPath:@"/Users/gbooker/Movies/TVShowsTests" inContext:moc];
+		[moc deleteObject:dir];
+		[SapphireMetaDataSupport deletePendingObjects];
+		NSArray *allMovies = doFetchRequest(SapphireMovieName, moc, nil);
+		NSArray *allShows = doFetchRequest(SapphireTVShowName, moc, nil);
+		NSArray *allGenres = doFetchRequest(SapphireGenreName, moc, nil);
+		NSArray *allCast = doFetchRequest(SapphireCastName, moc, nil);
+		NSArray *allDirectors = doFetchRequest(SapphireDirectorName, moc, nil);
+		
+		NSLog(@"Movies: %@\nShows: %@\nCast: %@\nGenres: %@\nDirectors: %@", allMovies, allShows, allCast, allGenres, allDirectors);
+	}
+#endif
 	
 	[pool release];
