GNUstep Core Data
0.1
|
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