GNUstep Core Data  0.1
NSPersistentStoreCoordinator.m
1 /* Implementation of the NSPersistentStoreCoordinator class for the GNUstep
2  Core Data framework.
3  Copyright (C) 2005 Free Software Foundation, Inc.
4 
5  Written by: Saso Kiselkov <diablos@manga.sk>
6  Date: August 2005
7 
8  This file is part of the GNUstep Core Data framework.
9 
10  This library is free software; you can redistribute it and/or
11  modify it under the terms of the GNU Lesser General Public
12  License as published by the Free Software Foundation; either
13  version 2.1 of the License, or (at your option) any later version.
14 
15  This library is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public
21  License along with this library; if not, write to the Free
22  Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
23  */
24 
25 #import "CoreDataHeaders.h"
26 #import "GSPersistentStore.h"
27 #import "GSSQLitePersistentStore.h"
28 
29 NSString
30  * const NSSQLiteStoreType = @"NSSQLiteStoreType",
31  * const NSXMLStoreType = @"NSXMLStoreType",
32  * const NSBinaryStoreType = @"NSBinaryStoreType",
33  * const NSInMemoryStoreType = @"NSInMemoryStoreType";
34 
35 NSString
36  * const NSReadOnlyPersistentStoreOption = @"NSReadOnlyPersistentStoreOption",
37  * const NSValidateXMLStoreOption = @"NSValidateXMLStoreOption";
38 
39 NSString
40  * const NSStoreTypeKey = @"NSStoreTypeKey",
41  * const NSStoreUUIDKey = @"NSStoreUUIDKey";
42 
43 @implementation NSPersistentStoreCoordinator
44 
52 static NSMutableDictionary * persistentStoreTypes = nil;
53 
54 // Add the basic store types to our knowledge base.
55 + (void) initialize
56 {
57  if (persistentStoreTypes == nil)
58  {
59  persistentStoreTypes = [[NSMutableDictionary alloc]
60  initWithObjectsAndKeys:
61  NSSQLiteStoreType, [GSSQLitePersistentStore class],
62 /*
63  NSXMLStoreType, [GSXMLPersistentStore class],
64  NSBinaryStoreType, [GSBinaryPersistentStore class],
65  NSInMemoryStoreType, [GSInMemoryPersistentStore class],*/
66  nil];
67  }
68 }
69 
70 + (void) addPersistentStoreType: (NSString *) type
71  handledByClass: (Class) newClass
72 {
73  Class oldClass;
74 
75  if ([newClass isKindOfClass: [GSPersistentStore class]] == NO)
76  {
77  [NSException raise: NSInvalidArgumentException
78  format: _(@"When adding a new store type, you must "
79  @"do so by subclassing GSPersistentStore "
80  @"and implementing it's abstract methods."),
81  [newClass className]];
82  }
83 
84  // warn about redefinition of already defined store types.
85  oldClass = [persistentStoreTypes objectForKey: type];
86  if (oldClass != nil && oldClass != newClass)
87  {
88  NSLog(_(@"WARNING: Replacing persistent store type %@, "
89  @"originally handled by class %@, with class %@."),
90  type, [oldClass className], [newClass className]);
91  }
92 
93  [persistentStoreTypes setObject: newClass forKey: type];
94 }
95 
96 + (NSArray *) supportedPersistentStoreTypes
97 {
98  return [persistentStoreTypes allKeys];
99 }
100 
101 - (void) dealloc
102 {
103  if (_acquiredModel)
104  {
105  [_model _decrementUseCount];
106  }
107  TEST_RELEASE(_model);
108 
109  TEST_RELEASE(_persistentStores);
110  TEST_RELEASE(_lock);
111 
112  [super dealloc];
113 }
114 
115 - (id) initWithManagedObjectModel: (NSManagedObjectModel *) model
116 {
117  if ((self = [self init]))
118  {
119  ASSIGN(_model, model);
120 
121  _persistentStores = [NSMutableDictionary new];
122  _lock = [NSRecursiveLock new];
123 
124  }
125  return self;
126 }
127 
128 - (NSManagedObjectModel *) managedObjectModel
129 {
130  return _model;
131 }
132 
133 - (id) addPersistentStoreWithType: (NSString *) storeType
134  configuration: (NSString *) configuration
135  URL: (NSURL *) aURL
136  options: (NSDictionary *) options
137  error: (NSError **) error
138 {
139  GSPersistentStore * store;
140  Class storeClass;
141 
142  storeClass = [persistentStoreTypes objectForKey: storeType];
143  if (storeClass == Nil)
144  {
145  SetNonNullError(error, [NSError
146  errorWithDomain: NSCoreDataErrorDomain
147  code: NSPersistentStoreInvalidTypeError
148  userInfo: nil]);
149 
150  return nil;
151  }
152 
153  // define what configurations are allowed
154  if (_configurationSet == NO)
155  {
156  _multipleConfigurationsAllowed = (configuration != nil);
157  _configurationSet = YES;
158  }
159  else if (_multipleConfigurationsAllowed == NO && configuration != nil)
160  {
161  SetNonNullError(error, [NSError
162  errorWithDomain: NSCoreDataErrorDomain
163  code: NSPersistentStoreIncompatibleSchemaError
164  userInfo: nil]);
165 
166  return nil;
167  }
168 
169  store = [[[storeClass alloc]
170  initWithURL: aURL
171  managedObjectModel: _model
172  configuration: configuration
173  options: options]
174  autorelease];
175  if (store == nil)
176  {
177  SetNonNullError(error, [NSError
178  errorWithDomain: NSCoreDataErrorDomain
179  code: NSPersistentStoreInitializationError
180  userInfo: nil]);
181 
182  return nil;
183  }
184 
185  [_persistentStores setObject: store forKey: aURL];
186 
187  return store;
188 }
189 
190 - (BOOL) removePersistentStore: (id) persistentStore
191  error: (NSError **) error
192 {
193  GSPersistentStore * store = persistentStore;
194 
195  // FIXME: what errors could occur here?
196  [_persistentStores removeObjectForKey: [store URL]];
197 
198  return YES;
199 }
200 
201 - (NSArray *) persistentStores
202 {
203  return [_persistentStores allValues];
204 }
205 
206 - (id) persistentStoreForURL: (NSURL *) aURL
207 {
208  return [_persistentStores objectForKey: aURL];
209 }
210 
211 - (NSURL *) URLForPersistentStore: (id) persistentStore
212 {
213  return [persistentStore URL];
214 }
215 
216 - (void) lock
217 {
218  [_lock lock];
219 }
220 
221 - (BOOL) tryLock
222 {
223  return [_lock tryLock];
224 }
225 
226 - (void) unlock
227 {
228  [_lock unlock];
229 }
230 
231 - (NSDictionary *) metadataForPersistentStore: (id) store
232 {
233  return [store metadata];
234 }
235 
236 - (NSManagedObjectID *) managedObjectIDForURIRepresentation: (NSURL *) uri
237 {
238  GSPersistentStore * store;
239  NSString * UUID;
240  unsigned long long uuid, idValue;
241  NSString * entityName;
242  NSEntityDescription * entity;
243  NSEnumerator * e;
244  NSArray * pathComponents;
245 
246  pathComponents = [[uri path] pathComponents];
247  if ([pathComponents count] != 3)
248  {
249  return nil;
250  }
251 
252  // find the persistent store with the ID's UUID
253  UUID = [pathComponents objectAtIndex: 0];
254  e = [[_persistentStores allValues] objectEnumerator];
255  while ((store = [e nextObject]) != nil)
256  {
257  if ([[[store metadata] objectForKey: NSStoreUUIDKey] isEqual: UUID])
258  {
259  break;
260  }
261  }
262  if (store == nil)
263  {
264  // store not found
265  return nil;
266  }
267 
268  // find the ID's entity
269  entityName = [pathComponents objectAtIndex: 1];
270  if ([store configuration] == nil)
271  {
272  entity = [[_model entitiesByName] objectForKey: entityName];
273  }
274  else
275  {
276  entity = [[_model _entitiesByNameForConfiguration: [store configuration]]
277  objectForKey: entityName];
278  }
279 
280  if (entity == nil)
281  {
282  // entity not found
283  return nil;
284  }
285 
286  if (sscanf([[pathComponents objectAtIndex: 2] cString], "%llX",
287  &idValue) != 1)
288  {
289  // malformed or no id value
290  return nil;
291  }
292 
293  return [[[NSManagedObjectID alloc]
294  _initWithEntity: entity
295  persistentStore: store
296  value: idValue]
297  autorelease];
298 }
299 
300 @end
Nn abstract superclass from which concrete implementations of various persistent store types are subc...
NSURL * URL()
Getting the store's URL.
NSString * configuration()
Getting the store's configuration.
For implementation notes see "Documentation/NSManagedObjectID.txt" in the source distribution of the ...