mirror of
https://github.com/gnustep/libs-gscoredata.git
synced 2025-02-14 07:31:18 +00:00
30c88829fc
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep@25765 72102866-910b-0410-8b05-ffd578937521
300 lines
7.6 KiB
Objective-C
300 lines
7.6 KiB
Objective-C
/* Implementation of the NSPersistentStoreCoordinator class for the GNUstep
|
|
Core Data framework.
|
|
Copyright (C) 2005 Free Software Foundation, Inc.
|
|
|
|
Written by: Saso Kiselkov <diablos@manga.sk>
|
|
Date: August 2005
|
|
|
|
This file is part of the GNUstep Core Data framework.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
|
|
*/
|
|
|
|
#import "CoreDataHeaders.h"
|
|
#import "GSPersistentStore.h"
|
|
#import "GSSQLitePersistentStore.h"
|
|
|
|
NSString
|
|
* const NSSQLiteStoreType = @"NSSQLiteStoreType",
|
|
* const NSXMLStoreType = @"NSXMLStoreType",
|
|
* const NSBinaryStoreType = @"NSBinaryStoreType",
|
|
* const NSInMemoryStoreType = @"NSInMemoryStoreType";
|
|
|
|
NSString
|
|
* const NSReadOnlyPersistentStoreOption = @"NSReadOnlyPersistentStoreOption",
|
|
* const NSValidateXMLStoreOption = @"NSValidateXMLStoreOption";
|
|
|
|
NSString
|
|
* const NSStoreTypeKey = @"NSStoreTypeKey",
|
|
* const NSStoreUUIDKey = @"NSStoreUUIDKey";
|
|
|
|
@implementation NSPersistentStoreCoordinator
|
|
|
|
/**
|
|
* This maps store type strings to classes that implement
|
|
* the specific store types. All must conform to the
|
|
* GSPersistentStore protocol. This dictionary is mutable
|
|
* in order to allow further addition of store types into
|
|
* it at run time.
|
|
*/
|
|
static NSMutableDictionary * persistentStoreTypes = nil;
|
|
|
|
// Add the basic store types to our knowledge base.
|
|
+ (void) initialize
|
|
{
|
|
if (persistentStoreTypes == nil)
|
|
{
|
|
persistentStoreTypes = [[NSMutableDictionary alloc]
|
|
initWithObjectsAndKeys:
|
|
NSSQLiteStoreType, [GSSQLitePersistentStore class],
|
|
/*
|
|
NSXMLStoreType, [GSXMLPersistentStore class],
|
|
NSBinaryStoreType, [GSBinaryPersistentStore class],
|
|
NSInMemoryStoreType, [GSInMemoryPersistentStore class],*/
|
|
nil];
|
|
}
|
|
}
|
|
|
|
+ (void) addPersistentStoreType: (NSString *) type
|
|
handledByClass: (Class) newClass
|
|
{
|
|
Class oldClass;
|
|
|
|
if ([newClass isKindOfClass: [GSPersistentStore class]] == NO)
|
|
{
|
|
[NSException raise: NSInvalidArgumentException
|
|
format: _(@"When adding a new store type, you must "
|
|
@"do so by subclassing GSPersistentStore "
|
|
@"and implementing it's abstract methods."),
|
|
[newClass className]];
|
|
}
|
|
|
|
// warn about redefinition of already defined store types.
|
|
oldClass = [persistentStoreTypes objectForKey: type];
|
|
if (oldClass != nil && oldClass != newClass)
|
|
{
|
|
NSLog(_(@"WARNING: Replacing persistent store type %@, "
|
|
@"originally handled by class %@, with class %@."),
|
|
type, [oldClass className], [newClass className]);
|
|
}
|
|
|
|
[persistentStoreTypes setObject: newClass forKey: type];
|
|
}
|
|
|
|
+ (NSArray *) supportedPersistentStoreTypes
|
|
{
|
|
return [persistentStoreTypes allKeys];
|
|
}
|
|
|
|
- (void) dealloc
|
|
{
|
|
if (_acquiredModel)
|
|
{
|
|
[_model _decrementUseCount];
|
|
}
|
|
TEST_RELEASE(_model);
|
|
|
|
TEST_RELEASE(_persistentStores);
|
|
TEST_RELEASE(_lock);
|
|
|
|
[super dealloc];
|
|
}
|
|
|
|
- (id) initWithManagedObjectModel: (NSManagedObjectModel *) model
|
|
{
|
|
if ((self = [self init]))
|
|
{
|
|
ASSIGN(_model, model);
|
|
|
|
_persistentStores = [NSMutableDictionary new];
|
|
_lock = [NSRecursiveLock new];
|
|
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (NSManagedObjectModel *) managedObjectModel
|
|
{
|
|
return _model;
|
|
}
|
|
|
|
- (id) addPersistentStoreWithType: (NSString *) storeType
|
|
configuration: (NSString *) configuration
|
|
URL: (NSURL *) aURL
|
|
options: (NSDictionary *) options
|
|
error: (NSError **) error
|
|
{
|
|
GSPersistentStore * store;
|
|
Class storeClass;
|
|
|
|
storeClass = [persistentStoreTypes objectForKey: storeType];
|
|
if (storeClass == Nil)
|
|
{
|
|
SetNonNullError(error, [NSError
|
|
errorWithDomain: NSCoreDataErrorDomain
|
|
code: NSPersistentStoreInvalidTypeError
|
|
userInfo: nil]);
|
|
|
|
return nil;
|
|
}
|
|
|
|
// define what configurations are allowed
|
|
if (_configurationSet == NO)
|
|
{
|
|
_multipleConfigurationsAllowed = (configuration != nil);
|
|
_configurationSet = YES;
|
|
}
|
|
else if (_multipleConfigurationsAllowed == NO && configuration != nil)
|
|
{
|
|
SetNonNullError(error, [NSError
|
|
errorWithDomain: NSCoreDataErrorDomain
|
|
code: NSPersistentStoreIncompatibleSchemaError
|
|
userInfo: nil]);
|
|
|
|
return nil;
|
|
}
|
|
|
|
store = [[[storeClass alloc]
|
|
initWithURL: aURL
|
|
managedObjectModel: _model
|
|
configuration: configuration
|
|
options: options]
|
|
autorelease];
|
|
if (store == nil)
|
|
{
|
|
SetNonNullError(error, [NSError
|
|
errorWithDomain: NSCoreDataErrorDomain
|
|
code: NSPersistentStoreInitializationError
|
|
userInfo: nil]);
|
|
|
|
return nil;
|
|
}
|
|
|
|
[_persistentStores setObject: store forKey: aURL];
|
|
|
|
return store;
|
|
}
|
|
|
|
- (BOOL) removePersistentStore: (id) persistentStore
|
|
error: (NSError **) error
|
|
{
|
|
GSPersistentStore * store = persistentStore;
|
|
|
|
// FIXME: what errors could occur here?
|
|
[_persistentStores removeObjectForKey: [store URL]];
|
|
|
|
return YES;
|
|
}
|
|
|
|
- (NSArray *) persistentStores
|
|
{
|
|
return [_persistentStores allValues];
|
|
}
|
|
|
|
- (id) persistentStoreForURL: (NSURL *) aURL
|
|
{
|
|
return [_persistentStores objectForKey: aURL];
|
|
}
|
|
|
|
- (NSURL *) URLForPersistentStore: (id) persistentStore
|
|
{
|
|
return [persistentStore URL];
|
|
}
|
|
|
|
- (void) lock
|
|
{
|
|
[_lock lock];
|
|
}
|
|
|
|
- (BOOL) tryLock
|
|
{
|
|
return [_lock tryLock];
|
|
}
|
|
|
|
- (void) unlock
|
|
{
|
|
[_lock unlock];
|
|
}
|
|
|
|
- (NSDictionary *) metadataForPersistentStore: (id) store
|
|
{
|
|
return [store metadata];
|
|
}
|
|
|
|
- (NSManagedObjectID *) managedObjectIDForURIRepresentation: (NSURL *) uri
|
|
{
|
|
GSPersistentStore * store;
|
|
NSString * UUID;
|
|
unsigned long long uuid, idValue;
|
|
NSString * entityName;
|
|
NSEntityDescription * entity;
|
|
NSEnumerator * e;
|
|
NSArray * pathComponents;
|
|
|
|
pathComponents = [[uri path] pathComponents];
|
|
if ([pathComponents count] != 3)
|
|
{
|
|
return nil;
|
|
}
|
|
|
|
// find the persistent store with the ID's UUID
|
|
UUID = [pathComponents objectAtIndex: 0];
|
|
e = [[_persistentStores allValues] objectEnumerator];
|
|
while ((store = [e nextObject]) != nil)
|
|
{
|
|
if ([[[store metadata] objectForKey: NSStoreUUIDKey] isEqual: UUID])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (store == nil)
|
|
{
|
|
// store not found
|
|
return nil;
|
|
}
|
|
|
|
// find the ID's entity
|
|
entityName = [pathComponents objectAtIndex: 1];
|
|
if ([store configuration] == nil)
|
|
{
|
|
entity = [[_model entitiesByName] objectForKey: entityName];
|
|
}
|
|
else
|
|
{
|
|
entity = [[_model _entitiesByNameForConfiguration: [store configuration]]
|
|
objectForKey: entityName];
|
|
}
|
|
|
|
if (entity == nil)
|
|
{
|
|
// entity not found
|
|
return nil;
|
|
}
|
|
|
|
if (sscanf([[pathComponents objectAtIndex: 2] cString], "%llX",
|
|
&idValue) != 1)
|
|
{
|
|
// malformed or no id value
|
|
return nil;
|
|
}
|
|
|
|
return [[[NSManagedObjectID alloc]
|
|
_initWithEntity: entity
|
|
persistentStore: store
|
|
value: idValue]
|
|
autorelease];
|
|
}
|
|
|
|
@end
|