GNUstep Core Data  0.1
NSPersistentStoreCoordinator.m
00001 /* Implementation of the NSPersistentStoreCoordinator class for the GNUstep
00002    Core Data framework.
00003    Copyright (C) 2005 Free Software Foundation, Inc.
00004 
00005    Written by:  Saso Kiselkov <diablos@manga.sk>
00006    Date: August 2005
00007 
00008    This file is part of the GNUstep Core Data framework.
00009 
00010    This library is free software; you can redistribute it and/or
00011    modify it under the terms of the GNU Lesser General Public
00012    License as published by the Free Software Foundation; either
00013    version 2.1 of the License, or (at your option) any later version.
00014 
00015    This library is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018    Lesser General Public License for more details.
00019 
00020    You should have received a copy of the GNU Lesser General Public
00021    License along with this library; if not, write to the Free
00022    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
00023  */
00024 
00025 #import "CoreDataHeaders.h"
00026 #import "GSPersistentStore.h"
00027 #import "GSSQLitePersistentStore.h"
00028 
00029 NSString
00030   * const NSSQLiteStoreType = @"NSSQLiteStoreType",
00031   * const NSXMLStoreType = @"NSXMLStoreType",
00032   * const NSBinaryStoreType = @"NSBinaryStoreType",
00033   * const NSInMemoryStoreType = @"NSInMemoryStoreType";
00034 
00035 NSString
00036   * const NSReadOnlyPersistentStoreOption = @"NSReadOnlyPersistentStoreOption",
00037   * const NSValidateXMLStoreOption = @"NSValidateXMLStoreOption";
00038 
00039 NSString
00040   * const NSStoreTypeKey = @"NSStoreTypeKey",
00041   * const NSStoreUUIDKey = @"NSStoreUUIDKey";
00042 
00043 @implementation NSPersistentStoreCoordinator
00044 
00052 static NSMutableDictionary * persistentStoreTypes = nil;
00053 
00054 // Add the basic store types to our knowledge base.
00055 + (void) initialize
00056 {
00057   if (persistentStoreTypes == nil)
00058     {
00059       persistentStoreTypes = /*
00060                 NSXMLStoreType, [GSXMLPersistentStore class],
00061         NSBinaryStoreType, [GSBinaryPersistentStore class],
00062         NSInMemoryStoreType, [GSInMemoryPersistentStore class],*/[[NSMutableDictionary alloc]
00063         initWithObjectsAndKeys:
00064         NSSQLiteStoreType, [GSSQLitePersistentStore class],
00065 
00066         nil];
00067     }
00068 }
00069 
00070 + (void) addPersistentStoreType: (NSString *) type
00071                  handledByClass: (Class) newClass
00072 {
00073   Class oldClass;
00074 
00075   if ([newClass isKindOfClass: [GSPersistentStore class]] == NO)
00076     {
00077       [NSException raise: NSInvalidArgumentException
00078                   format: _(@"When adding a new store type, you must "
00079                             @"do so by subclassing GSPersistentStore "
00080                             @"and implementing it's abstract methods."),
00081                             [newClass className]];
00082     }
00083 
00084   // warn about redefinition of already defined store types.
00085   oldClass = [persistentStoreTypes objectForKey: type];
00086   if (oldClass != nil && oldClass != newClass)
00087     {
00088       NSLog(_(@"WARNING: Replacing persistent store type %@, "
00089             @"originally handled by class %@, with class %@."),
00090         type, [oldClass className], [newClass className]);
00091     }
00092 
00093   [persistentStoreTypes setObject: newClass forKey: type];
00094 }
00095 
00096 + (NSArray *) supportedPersistentStoreTypes
00097 {
00098   return [persistentStoreTypes allKeys];
00099 }
00100 
00101 - (void) dealloc
00102 {
00103   if (_acquiredModel)
00104     {
00105       [_model _decrementUseCount];
00106     }
00107   TEST_RELEASE(_model);
00108 
00109   TEST_RELEASE(_persistentStores);
00110   TEST_RELEASE(_lock);
00111 
00112   [super dealloc];
00113 }
00114 
00115 - (id) initWithManagedObjectModel: (NSManagedObjectModel *) model
00116 {
00117         if ((self = [self init]))
00118     {
00119       ASSIGN(_model, model);
00120 
00121       _persistentStores = [NSMutableDictionary new];
00122       _lock = [NSRecursiveLock new];
00123 
00124     }
00125         return self;
00126 }
00127 
00128 - (NSManagedObjectModel *) managedObjectModel
00129 {
00130   return _model;
00131 }
00132 
00133 - (id) addPersistentStoreWithType: (NSString *) storeType
00134                     configuration: (NSString *) configuration
00135                               URL: (NSURL *) aURL
00136                           options: (NSDictionary *) options
00137                             error: (NSError **) error
00138 {
00139   GSPersistentStore * store;
00140   Class storeClass;
00141 
00142   storeClass = [persistentStoreTypes objectForKey: storeType];
00143   if (storeClass == Nil)
00144     {
00145       SetNonNullError(error, [NSError
00146         errorWithDomain: NSCoreDataErrorDomain
00147                    code: NSPersistentStoreInvalidTypeError
00148                userInfo: nil]);
00149 
00150       return nil;
00151     }
00152 
00153   // define what configurations are allowed
00154   if (_configurationSet == NO)
00155     {
00156       _multipleConfigurationsAllowed = (configuration != nil);
00157       _configurationSet = YES;
00158     }
00159   else if (_multipleConfigurationsAllowed == NO && configuration != nil)
00160     {
00161       SetNonNullError(error, [NSError
00162         errorWithDomain: NSCoreDataErrorDomain
00163                    code: NSPersistentStoreIncompatibleSchemaError
00164                userInfo: nil]);
00165 
00166       return nil;
00167     }
00168 
00169   store = [[[storeClass alloc]
00170            initWithURL: aURL
00171     managedObjectModel: _model
00172          configuration: configuration
00173                options: options]
00174     autorelease];
00175   if (store == nil)
00176     {
00177       SetNonNullError(error, [NSError
00178         errorWithDomain: NSCoreDataErrorDomain
00179                    code: NSPersistentStoreInitializationError
00180                userInfo: nil]);
00181 
00182       return nil;
00183     }
00184 
00185   [_persistentStores setObject: store forKey: aURL];
00186 
00187   return store;
00188 }
00189 
00190 - (BOOL) removePersistentStore: (id) persistentStore
00191                          error: (NSError **) error
00192 {
00193   GSPersistentStore * store = persistentStore;
00194 
00195   // FIXME: what errors could occur here?
00196   [_persistentStores removeObjectForKey: [store URL]];
00197 
00198   return YES;
00199 }
00200 
00201 - (NSArray *) persistentStores
00202 {
00203   return [_persistentStores allValues];
00204 }
00205 
00206 - (id) persistentStoreForURL: (NSURL *) aURL
00207 {
00208   return [_persistentStores objectForKey: aURL];
00209 }
00210 
00211 - (NSURL *) URLForPersistentStore: (id) persistentStore
00212 {
00213   return [persistentStore URL];
00214 }
00215 
00216 - (void) lock
00217 {
00218   [_lock lock];
00219 }
00220 
00221 - (BOOL) tryLock
00222 {
00223   return [_lock tryLock];
00224 }
00225 
00226 - (void) unlock
00227 {
00228   [_lock unlock];
00229 }
00230 
00231 - (NSDictionary *) metadataForPersistentStore: (id) store
00232 {
00233   return [store metadata];
00234 }
00235 
00236 - (NSManagedObjectID *) managedObjectIDForURIRepresentation: (NSURL *) uri
00237 {
00238   GSPersistentStore * store;
00239   NSString * UUID;
00240   unsigned long long uuid, idValue;
00241   NSString * entityName;
00242   NSEntityDescription * entity;
00243   NSEnumerator * e;
00244   NSArray * pathComponents;
00245 
00246   pathComponents = [[uri path] pathComponents];
00247   if ([pathComponents count] != 3)
00248     {
00249       return nil;
00250     }
00251 
00252   // find the persistent store with the ID's UUID
00253   UUID = [pathComponents objectAtIndex: 0];
00254   e = [[_persistentStores allValues] objectEnumerator];
00255   while ((store = [e nextObject]) != nil)
00256     {
00257       if ([[[store metadata] objectForKey: NSStoreUUIDKey] isEqual: UUID])
00258         {
00259           break;
00260         }
00261     }
00262   if (store == nil)
00263     {
00264       // store not found
00265       return nil;
00266     }
00267 
00268   // find the ID's entity
00269   entityName = [pathComponents objectAtIndex: 1];
00270   if ([store configuration] == nil)
00271     {
00272       entity = [[_model entitiesByName] objectForKey: entityName];
00273     }
00274   else
00275     {
00276       entity = [[_model _entitiesByNameForConfiguration: [store configuration]]
00277         objectForKey: entityName];
00278     }
00279 
00280   if (entity == nil)
00281     {
00282       // entity not found
00283       return nil;
00284     }
00285 
00286   if (sscanf([[pathComponents objectAtIndex: 2] cString], "%llX",
00287     &idValue) != 1)
00288     {
00289       // malformed or no id value
00290       return nil;
00291     }
00292 
00293   return [[[NSManagedObjectID alloc]
00294     _initWithEntity: entity
00295     persistentStore: store
00296               value: idValue]
00297     autorelease];
00298 }
00299 
00300 @end