2010-10-20 16:17:24 +00:00
|
|
|
/* Copyright (c)2008 Dan Knapp
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
|
this software and associated documentation files (the "Software"), to deal in
|
|
|
|
the Software without restriction, including without limitation the rights to
|
|
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
|
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
|
|
subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
|
|
copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
|
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
|
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
2010-10-20 16:17:24 +00:00
|
|
|
#import "NSInMemoryPersistentStore.h"
|
|
|
|
#import "NSManagedObjectID-Private.h"
|
2020-05-11 15:52:05 +00:00
|
|
|
#import "NSXMLPersistentStore.h"
|
|
|
|
#import <CoreData/NSManagedObject.h>
|
|
|
|
#import <CoreData/NSManagedObjectModel.h>
|
|
|
|
#import <CoreData/NSPersistentStoreCoordinator.h>
|
2010-10-20 16:17:24 +00:00
|
|
|
#import <Foundation/NSRaise.h>
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
NSString *const NSStoreTypeKey = @"NSStoreTypeKey";
|
|
|
|
NSString *const NSStoreUUIDKey = @"NSStoreUUIDKey";
|
2010-10-20 16:17:24 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
NSString *const NSXMLStoreType = @"XML";
|
|
|
|
NSString *const NSInMemoryStoreType = @"Memory";
|
|
|
|
NSString *const NSSQLiteStoreType = @"SQLite";
|
|
|
|
NSString *const NSBinaryStoreType = @"Binary";
|
|
|
|
NSString *const NSMigratePersistentStoresAutomaticallyOption =
|
2020-05-12 18:51:39 +00:00
|
|
|
@"NSMigratePersistentStoresAutomaticallyOption";
|
2010-10-20 16:17:24 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
NSString *const NSPersistentStoreCoordinatorStoresDidChangeNotification =
|
2020-05-12 18:51:39 +00:00
|
|
|
@"NSPersistentStoreCoordinatorStoresDidChangeNotification";
|
2020-05-11 15:52:05 +00:00
|
|
|
NSString *const NSAddedPersistentStoresKey = @"NSAddedPersistentStoresKey";
|
|
|
|
NSString *const NSRemovedPersistentStoresKey = @"NSRemovedPersistentStoresKey";
|
|
|
|
NSString *const NSUUIDChangedPersistentStoresKey =
|
2020-05-12 18:51:39 +00:00
|
|
|
@"NSUUIDChangedPersistentStoresKey";
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2019-01-04 23:53:27 +00:00
|
|
|
NSString *const NSPersistentStoreSaveConflictsErrorKey = @"conflictList";
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
NSString *const NSInferMappingModelAutomaticallyOption =
|
2020-05-12 18:51:39 +00:00
|
|
|
@"NSInferMappingModelAutomaticallyOption";
|
2020-05-11 15:52:05 +00:00
|
|
|
NSString *const NSReadOnlyPersistentStoreOption =
|
2020-05-12 18:51:39 +00:00
|
|
|
@"NSReadOnlyPersistentStoreOption";
|
2024-03-10 20:35:07 +00:00
|
|
|
NSString *const NSSQLiteManualVacuumOption = @"NSSQLiteManualVacuumOption";
|
2021-03-05 03:00:28 +00:00
|
|
|
NSString *const NSStoreModelVersionHashesKey =
|
|
|
|
@"NSStoreModelVersionHashesKey";
|
2019-06-11 01:52:52 +00:00
|
|
|
|
2008-06-17 16:37:08 +00:00
|
|
|
@implementation NSPersistentStoreCoordinator
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
static NSMutableDictionary *_storeTypes = nil;
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
+ (void) initialize {
|
|
|
|
if (self == [NSPersistentStoreCoordinator class]) {
|
|
|
|
_storeTypes = [NSMutableDictionary new];
|
|
|
|
[_storeTypes setObject: [NSInMemoryPersistentStore class]
|
|
|
|
forKey: NSInMemoryStoreType];
|
|
|
|
[_storeTypes setObject: [NSXMLPersistentStore class]
|
|
|
|
forKey: NSXMLStoreType];
|
|
|
|
}
|
2010-10-20 16:17:24 +00:00
|
|
|
}
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
+ (NSDictionary *) registeredStoreTypes {
|
2010-10-20 16:17:24 +00:00
|
|
|
return _storeTypes;
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
+ (void) registerStoreClass: (Class) storeClass
|
2020-05-12 00:04:26 +00:00
|
|
|
forStoreType: (NSString *) storeType
|
|
|
|
{
|
2020-05-11 15:52:05 +00:00
|
|
|
[_storeTypes setObject: storeClass forKey: storeType];
|
2010-10-20 16:17:24 +00:00
|
|
|
}
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- initWithManagedObjectModel: (NSManagedObjectModel *) model {
|
|
|
|
_lock = [[NSLock alloc] init];
|
|
|
|
_model = [model retain];
|
|
|
|
_stores = [[NSMutableArray alloc] init];
|
|
|
|
return self;
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (void) dealloc {
|
|
|
|
[_lock release];
|
|
|
|
[_model release];
|
|
|
|
[_stores release];
|
|
|
|
[super dealloc];
|
2010-10-20 16:17:24 +00:00
|
|
|
}
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (NSManagedObjectModel *) managedObjectModel {
|
|
|
|
return _model;
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (NSPersistentStore *) addPersistentStoreWithType: (NSString *) storeType
|
|
|
|
configuration: (NSString *) configuration
|
|
|
|
URL: (NSURL *) storeURL
|
|
|
|
options: (NSDictionary *) options
|
2020-05-12 00:04:26 +00:00
|
|
|
error: (NSError **) error
|
|
|
|
{
|
2020-05-11 15:52:05 +00:00
|
|
|
/* It appears that this method will determine the store type if it is nil */
|
|
|
|
if (storeType == nil) {
|
|
|
|
|
|
|
|
for (Class class in [_storeTypes allValues]) {
|
|
|
|
NSDictionary *metadata =
|
2020-05-12 18:51:39 +00:00
|
|
|
[class metadataForPersistentStoreWithURL: storeURL
|
|
|
|
error: nil];
|
2020-05-11 15:52:05 +00:00
|
|
|
if ((storeType = [metadata objectForKey: NSStoreTypeKey]) != nil)
|
|
|
|
break;
|
|
|
|
}
|
2010-10-20 16:17:24 +00:00
|
|
|
}
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
Class class = [[[self class] registeredStoreTypes] objectForKey: storeType];
|
|
|
|
NSAtomicStore *store = [[[class alloc]
|
2020-05-12 18:51:39 +00:00
|
|
|
initWithPersistentStoreCoordinator: self
|
|
|
|
configurationName: configuration
|
|
|
|
URL: storeURL
|
|
|
|
options: options] autorelease];
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
if (![store load: error])
|
|
|
|
return nil;
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
[_stores addObject: store];
|
|
|
|
|
|
|
|
return store;
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (BOOL) setURL: (NSURL *) url forPersistentStore: (NSPersistentStore *) store {
|
|
|
|
[store setURL: url];
|
|
|
|
return YES;
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (BOOL) removePersistentStore: (NSPersistentStore *) store
|
2020-05-12 00:04:26 +00:00
|
|
|
error: (NSError **) error
|
|
|
|
{
|
2020-05-11 15:52:05 +00:00
|
|
|
NSArray *remove = [NSArray arrayWithObject: store];
|
|
|
|
NSDictionary *userInfo =
|
2020-05-12 18:51:39 +00:00
|
|
|
[NSDictionary dictionaryWithObject: remove
|
|
|
|
forKey: NSRemovedPersistentStoresKey];
|
2020-05-11 15:52:05 +00:00
|
|
|
|
|
|
|
[store willRemoveFromPersistentStoreCoordinator: self];
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
[[NSNotificationCenter defaultCenter]
|
2020-05-12 18:51:39 +00:00
|
|
|
postNotificationName:
|
|
|
|
NSPersistentStoreCoordinatorStoresDidChangeNotification
|
|
|
|
object: self
|
|
|
|
userInfo: userInfo];
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
[_stores removeObjectIdenticalTo: store];
|
|
|
|
|
|
|
|
return YES;
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (NSPersistentStore *) migratePersistentStore: (NSPersistentStore *) store
|
|
|
|
toURL: (NSURL *) URL
|
|
|
|
options: (NSDictionary *) options
|
|
|
|
withType: (NSString *) storeType
|
2020-05-12 00:04:26 +00:00
|
|
|
error: (NSError **) error
|
|
|
|
{
|
2008-06-17 16:37:08 +00:00
|
|
|
NSUnimplementedMethod();
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (NSArray *) persistentStores {
|
|
|
|
return _stores;
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (NSPersistentStore *) persistentStoreForURL: (NSURL *) URL {
|
|
|
|
/* This only returns a store if it exists in the coordinator */
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
for (NSPersistentStore *check in _stores) {
|
|
|
|
if ([[check URL] isEqual: URL])
|
|
|
|
return check;
|
|
|
|
}
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
return nil;
|
2010-10-20 16:17:24 +00:00
|
|
|
}
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (NSURL *) URLForPersistentStore: (NSPersistentStore *) store {
|
|
|
|
return [store URL];
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (void) lock {
|
|
|
|
[_lock lock];
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (BOOL) tryLock {
|
|
|
|
return [_lock tryLock];
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (void) unlock {
|
|
|
|
[_lock unlock];
|
2010-10-20 16:17:24 +00:00
|
|
|
}
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (NSDictionary *) metadataForPersistentStore: (NSPersistentStore *) store {
|
|
|
|
return [store metadata];
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (void) setMetadata: (NSDictionary *) value
|
2020-05-12 18:51:39 +00:00
|
|
|
forPersistentStore: (NSPersistentStore *) store
|
2020-05-12 00:04:26 +00:00
|
|
|
{
|
2020-05-11 15:52:05 +00:00
|
|
|
[store setMetadata: value];
|
2010-10-20 16:17:24 +00:00
|
|
|
}
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
+ (BOOL) setMetadata: (NSDictionary *) metadata
|
2020-05-12 18:51:39 +00:00
|
|
|
forPersistentStoreOfType: (NSString *) storeType
|
|
|
|
URL: (NSURL *) url
|
|
|
|
error: (NSError **) error
|
2020-05-12 00:04:26 +00:00
|
|
|
{
|
2020-05-11 15:52:05 +00:00
|
|
|
Class check = [[self registeredStoreTypes] objectForKey: storeType];
|
|
|
|
|
|
|
|
return [check setMetadata: metadata
|
2020-05-12 18:51:39 +00:00
|
|
|
forPersistentStoreWithURL: url
|
|
|
|
error: error];
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
+ (NSDictionary *) metadataForPersistentStoreOfType: (NSString *) storeType
|
|
|
|
URL: (NSURL *) url
|
2020-05-12 00:04:26 +00:00
|
|
|
error: (NSError **) error
|
|
|
|
{
|
2020-05-11 15:52:05 +00:00
|
|
|
Class check = [[self registeredStoreTypes] objectForKey: storeType];
|
|
|
|
|
|
|
|
return [check metadataForPersistentStoreWithURL: url error: error];
|
2010-10-20 16:17:24 +00:00
|
|
|
}
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-12 00:04:26 +00:00
|
|
|
- (NSPersistentStore *) _persistentStoreWithIdentifier: (NSString *) identifier
|
|
|
|
{
|
2020-05-11 15:52:05 +00:00
|
|
|
for (NSPersistentStore *check in _stores)
|
|
|
|
if ([[check identifier] isEqualToString: identifier])
|
|
|
|
return check;
|
|
|
|
|
2008-06-17 16:37:08 +00:00
|
|
|
return nil;
|
2020-05-11 15:52:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSPersistentStore *) _persistentStoreForObjectID:
|
2020-05-12 18:51:39 +00:00
|
|
|
(NSManagedObjectID *) objectID
|
2020-05-12 00:04:26 +00:00
|
|
|
{
|
2020-05-11 15:52:05 +00:00
|
|
|
NSEntityDescription *entity = [objectID entity];
|
|
|
|
NSString *storeIdentifier = [objectID storeIdentifier];
|
|
|
|
NSPersistentStore *check =
|
2020-05-12 18:51:39 +00:00
|
|
|
[self _persistentStoreWithIdentifier: storeIdentifier];
|
2020-05-11 15:52:05 +00:00
|
|
|
|
|
|
|
if (check != nil)
|
|
|
|
return check;
|
|
|
|
|
|
|
|
NSManagedObjectModel *model = [self managedObjectModel];
|
|
|
|
|
|
|
|
if ([_stores count] == 0) {
|
|
|
|
[NSException
|
2020-05-12 18:51:39 +00:00
|
|
|
raise: NSInvalidArgumentException
|
|
|
|
format: @"-[%@ %s] no persistent stores", [self class], _cmd];
|
2020-05-11 15:52:05 +00:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (check in _stores) {
|
|
|
|
NSString *configurationName = [check configurationName];
|
|
|
|
|
|
|
|
if (configurationName == nil) {
|
|
|
|
NSArray *entities =
|
2020-05-12 18:51:39 +00:00
|
|
|
[model entitiesForConfiguration: configurationName];
|
2020-05-11 15:52:05 +00:00
|
|
|
|
|
|
|
if ([entities containsObject: entity])
|
|
|
|
return check;
|
|
|
|
}
|
2010-10-20 16:17:24 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
return [_stores objectAtIndex: 0];
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (NSPersistentStore *) _persistentStoreForObject: (NSManagedObject *) object {
|
|
|
|
return [self _persistentStoreForObjectID: [object objectID]];
|
2010-10-20 16:17:24 +00:00
|
|
|
}
|
2008-06-17 16:37:08 +00:00
|
|
|
|
2020-05-11 15:52:05 +00:00
|
|
|
- (NSManagedObjectID *) managedObjectIDForURIRepresentation: (NSURL *) URL {
|
|
|
|
NSString *scheme = [URL scheme];
|
|
|
|
NSString *host = [URL host];
|
|
|
|
NSString *path = [URL path];
|
|
|
|
NSString *referenceObject = [path lastPathComponent];
|
|
|
|
NSString *entityName =
|
2020-05-12 18:51:39 +00:00
|
|
|
[[path stringByDeletingLastPathComponent] lastPathComponent];
|
2020-05-11 15:52:05 +00:00
|
|
|
NSManagedObjectModel *model = [self managedObjectModel];
|
|
|
|
NSEntityDescription *entity =
|
2020-05-12 18:51:39 +00:00
|
|
|
[[model entitiesByName] objectForKey: entityName];
|
2020-05-11 15:52:05 +00:00
|
|
|
|
|
|
|
return [(NSAtomicStore *) [self _persistentStoreWithIdentifier: host]
|
2020-05-12 18:51:39 +00:00
|
|
|
objectIDForEntity: entity
|
|
|
|
referenceObject: referenceObject];
|
2008-06-17 16:37:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@end
|