GNUstep Core Data 0.1
NSEntityDescription.m
1/* Implementation of the NSEntityDescription 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
27// Ensures the entity can be edited. Raises an NSGenericException
28// if the passed model is not nil and is not editable, with a reason
29// set to `reason'.
30static inline void EnsureEntityEditable(NSManagedObjectModel * model,
31 NSString * reason)
32{
33 if (model != nil && [model _isEditable] == NO)
34 {
35 [NSException raise: NSGenericException format: reason];
36 }
37}
38
39
40@implementation NSEntityDescription
41
42
43- (NSDictionary *) _filteredPropertiesOfClass: (Class) aClass
44{
45 NSMutableDictionary * dict;
46 NSEnumerator * e;
47 NSPropertyDescription * property;
48
49 dict = [NSMutableDictionary dictionaryWithCapacity: [_properties count]];
50 e = [_properties objectEnumerator];
51 while ((property = [e nextObject]) != nil)
52 {
53 if (aClass == Nil || [property isKindOfClass: aClass])
54 {
55 [dict setObject: property forKey: [property name]];
56 }
57 }
58
59 return [[dict copy] autorelease];
60}
61
62- (NSDictionary *) _fetchedPropertiesByName
63{
64 return [self _filteredPropertiesOfClass: [NSFetchedPropertyDescription
65 class]];
66}
67
68+ (NSEntityDescription *) entityForName: (NSString *) entityName
69 inManagedObjectContext: (NSManagedObjectContext *) ctxt
70{
71 return [[[[ctxt persistentStoreCoordinator] managedObjectModel]
72 entitiesByName] objectForKey: entityName];
73}
74
75+ (id) insertNewObjectForEntityForName: (NSString *) anEntityName
76 inManagedObjectContext: (NSManagedObjectContext *) aContext
77{
78 NSEntityDescription * entity;
79 Class entityClass;
80 NSManagedObjectModel * model;
81
82 model = [[aContext persistentStoreCoordinator] managedObjectModel];
83 entity = [[model entitiesByName] objectForKey: anEntityName];
84
85 entityClass = NSClassFromString([entity managedObjectClassName]);
86
87 return [[[entityClass alloc]
88 initWithEntity: entity insertIntoManagedObjectContext: aContext]
89 autorelease];
90}
91
92- (void) dealloc
93{
94 TEST_RELEASE(_name);
95
96 // let go of our properties
97 [_properties makeObjectsPerformSelector: @selector(_setEntity:)
98 withObject: nil];
99 TEST_RELEASE(_properties);
100
101 TEST_RELEASE(_userInfo);
102 TEST_RELEASE(_managedObjectClassName);
103
104 [_subentities makeObjectsPerformSelector: @selector(setSuperentity:)
105 withObject: nil];
106
107 TEST_RELEASE(_subentities);
108
109 [super dealloc];
110}
111
112
113
114- (NSString *) name
115{
116 return _name;
117}
118
119- (void) setName: (NSString *) aName
120{
121 EnsureEntityEditable(_model, _(@"Tried to set the name of an "
122 @"entity alredy in use."));
123 ASSIGN(_name, aName);
124}
125
126
127
128- (NSManagedObjectModel *) managedObjectModel
129{
130 return _model;
131}
132
133
134
135- (NSString *) managedObjectClassName
136{
137 return _managedObjectClassName;
138}
139
140- (void) setManagedObjectClassName: (NSString *) aName
141{
142 EnsureEntityEditable(_model, _(@"Tried to set the managed object "
143 @"class name of an entity already in use"));
144 ASSIGN(_managedObjectClassName, aName);
145}
146
147
148
149- (BOOL) isAbstract
150{
151 return _abstract;
152}
153
154- (void) setAbstract: (BOOL) flag
155{
156 EnsureEntityEditable(_model, _(@"Tried to set abstractness "
157 @"of an entity already in use"));
158 _abstract = flag;
159}
160
165- (BOOL) _isSubentityOfEntity: (NSEntityDescription *) otherEntity
166{
167 NSEntityDescription * entity;
168
169 for (entity = self; entity != nil; entity = [entity superentity])
170 {
171 if ([entity isEqual: otherEntity])
172 {
173 return YES;
174 }
175 }
176
177 return NO;
178}
179
180- (NSDictionary *) subentitiesByName
181{
182 NSMutableDictionary * dict;
183 NSEnumerator * e;
184 NSEntityDescription * subentity;
185
186 dict = [NSMutableDictionary dictionaryWithCapacity: [_subentities count]];
187 e = [_subentities objectEnumerator];
188 while ((subentity = [e nextObject]) != nil)
189 {
190 [dict setObject: subentity forKey: [subentity name]];
191 }
192
193 return [[dict copy] autorelease];
194}
195
196- (NSArray *) subentities
197{
198 return _subentities;
199}
200
201- (void) setSubentities: (NSArray *) someEntities
202{
203 EnsureEntityEditable(_model, _(@"Tried to set sub-entities of an entity "
204 @"already in use"));
205 ASSIGN(_subentities, [[someEntities copy] autorelease]);
206}
207
208
209- (NSEntityDescription *) superentity
210{
211 return _superentity;
212}
213
214- (void) _setSuperentity: (NSEntityDescription *) entity
215{
216 EnsureEntityEditable(_model, _(@"Tried to set super-entity of an entity "
217 @"already in use"));
218 _superentity = entity;
219}
220
221
222
223- (NSDictionary *) propertiesByName
224{
225 return [self filteredPropertiesOfClass: Nil];
226}
227
228- (NSArray *) properties
229{
230 return _properties;
231}
232
233- (void) setProperties: (NSArray *) someProperties
234{
235 EnsureEntityEditable(_model, _(@"Tried to set properties "
236 @"of an entity already in use"));
237 ASSIGN(_properties, [[someProperties copy] autorelease]);
238 [_properties makeObjectsPerformSelector: @selector(_setEntity:)
239 withObject: self];
240}
241
242- (NSDictionary *) userInfo
243{
244 return _userInfo;
245}
246
247- (void) setUserInfo: (NSDictionary *) userInfo
248{
249 EnsureEntityEditable(_model, _(@"Tried to set properties "
250 @"of an entity already in use"));
251 ASSIGN(_userInfo, [[userInfo copy] autorelease]);
252}
253
254
255
256- (NSDictionary *) attributesByName
257{
258 return [self _filteredPropertiesOfClass: [NSAttributeDescription class]];
259}
260
261- (NSDictionary *) relationshipsByName
262{
263 return [self _filteredPropertiesOfClass: [NSRelationshipDescription class]];
264}
265
266- (NSArray *) relationshipsWithDestinationEntity:
267 (NSEntityDescription *) destEntity
268{
269 NSMutableArray * array;
270 NSEnumerator * e;
271 NSRelationshipDescription * relationship;
272 Class relationshipClass;
273
274 array = [NSMutableArray arrayWithCapacity: [_properties count]];
275 relationshipClass = [NSRelationshipDescription class];
276
277 e = [_properties objectEnumerator];
278 while ((relationship = [e nextObject]) != nil)
279 {
280 if ([relationship isKindOfClass: relationshipClass] &&
281 [relationship destinationEntity] == destEntity)
282 {
283 [array addObject: relationship];
284 }
285 }
286
287 return [[array copy] autorelease];
288}
289
290// NSCopying
291
292- (id) copyWithZone: (NSZone *) aZone
293{
294 NSEntityDescription * entity;
295
296 entity = [[NSEntityDescription allocWithZone: aZone] init];
297
298 [entity setName: _name];
299 [entity setManagedObjectClassName: _managedObjectClassName];
300 [entity setAbstract: _abstract];
301 [entity setSubentities: _subentities];
302 [entity _setSuperentity: _superentity];
303
304 return entity;
305}
306
307// NSCoding
308
309- (id) initWithCoder: (NSCoder *) coder
310{
311 if ((self = [self init]))
312 {
313 if ([coder allowsKeyedCoding])
314 {
315 ASSIGN(_name, [coder decodeObjectForKey: @"Name"]);
316 _abstract = [coder decodeBoolForKey: @"Abstract"];
317 ASSIGN(_managedObjectClassName,
318 [coder decodeObjectForKey: @"ManagedObjectClassName"]);
319 ASSIGN(_properties, [coder decodeObjectForKey: @"Properties"]);
320 ASSIGN(_userInfo, [coder decodeObjectForKey: @"UserInfo"]);
321 ASSIGN(_subentities, [coder decodeObjectForKey: @"SubEntities"]);
322 _superentity = [coder decodeObjectForKey: @"SuperEntity"];
323 _model = [coder decodeObjectForKey: @"ManagedObjectModel"];
324 _modelRefCount = [coder decodeIntForKey: @"ModelReferenceCount"];
325 }
326 else
327 {
328 ASSIGN(_name, [coder decodeObject]);
329 [coder decodeValueOfObjCType: @encode(BOOL) at: &_abstract];
330 ASSIGN(_managedObjectClassName, [coder decodeObject]);
331 ASSIGN(_properties, [coder decodeObject]);
332 ASSIGN(_userInfo, [coder decodeObject]);
333 ASSIGN(_subentities, [coder decodeObject]);
334 _superentity = [coder decodeObject];
335 _model = [coder decodeObject];
336 [coder decodeValueOfObjCType: @encode(unsigned int)
337 at: &_modelRefCount];
338 }
339
340 }
341 return self;
342}
343
344- (void) encodeWithCoder: (NSCoder *) coder
345{
346 if ([coder allowsKeyedCoding])
347 {
348 [coder encodeObject: _name forKey: @"Name"];
349 [coder encodeBool: _abstract forKey: @"Abstract"];
350 [coder encodeObject: _managedObjectClassName
351 forKey: @"ManagedObjectClassName"];
352 [coder encodeObject: _properties forKey: @"Properties"];
353 [coder encodeObject: _userInfo forKey: @"UserInfo"];
354 [coder encodeObject: _subentities forKey: @"SubEntities"];
355 [coder encodeObject: _superentity forKey: @"SuperEntity"];
356 [coder encodeObject: _model forKey: @"ManagedObjectModel"];
357 [coder encodeInt: _modelRefCount forKey: @"ModelReferenceCount"];
358 }
359 else
360 {
361 [coder encodeObject: _name];
362 [coder encodeValueOfObjCType: @encode(BOOL) at: &_abstract];
363 [coder encodeObject: _managedObjectClassName];
364 [coder encodeObject: _properties];
365 [coder encodeObject: _userInfo];
366 [coder encodeObject: _subentities];
367 [coder encodeObject: _superentity];
368 [coder encodeObject: _model];
369 [coder encodeValueOfObjCType: @encode(unsigned int)
370 at: &_modelRefCount];
371 }
372}
373
389- (void) _addReferenceToManagedObjectModel: (NSManagedObjectModel *) aModel
390{
391 // don't allow re-setting the owner like this
392 NSAssert(aModel != nil && (_model == nil || _model == aModel),
393 _(@"Attempted to forcefully change the reference from an entity "
394 @"to it's managed object model owner or ``nil'' model argument "
395 @"passed."));
396
397 _model = aModel;
398 _modelRefCount++;
399}
400
401- (void) _removeReferenceToManagedObjectModel: (NSManagedObjectModel *) aModel
402{
403 NSAssert(_model == aModel, _(@"Attempted to forcefully remove the "
404 @"reference from an entity to it's managed object model by some other, "
405 @"unrelated model."));
406 NSAssert(_modelRefCount > 0, _(@"Attempted to underflow the "
407 @"reference count from an entity to it's managed object model."));
408
409 _modelRefCount--;
410 if (_modelRefCount == 0)
411 {
412 _model = nil;
413 }
414}
415
416@end