4 Copyright (C) 1996 Free Software Foundation, Inc.
6 Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
9 This file is part of the GNUstep Database Library.
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Library General Public
13 License as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Library General Public License for more details.
21 You should have received a copy of the GNU Library General Public
22 License along with this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation,
24 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 /* Include the code from EOKeyValueCoding.m and EOCustomValues.m here because
32 they contain categories to various classes from Foundation that don't get
33 linked into the client application since no one refers them. The NeXT linker
34 knows how to deal with this but all the other linkers don't... */
36 # import "EOCustomValues.m"
39 void EOModel_linkCategories(void) {
40 void EOAccess_EOCustomValues_link(void);
42 EOAccess_EOCustomValues_link();
45 @implementation EOModel
47 - (id)copyWithZone:(NSZone *)_zone {
51 + (NSString*)findPathForModelNamed:(NSString*)modelName {
53 NSBundle* bundle = [NSBundle mainBundle];
54 NSString* modelPath = [bundle pathForResource:modelName ofType:@"eomodel"];
55 NSString* paths[] = { @"~/Library/Models",
56 @"/LocalLibrary/Models",
57 @"/NextLibrary/Models",
63 for(i = 0; paths[i]; i++) {
64 bundle = [NSBundle bundleWithPath:paths[i]];
65 modelPath = [bundle pathForResource:modelName ofType:@"eomodel"];
73 if ((self = [super init])) {
74 NSNotificationCenter *nc;
76 nc = [NSNotificationCenter defaultCenter];
77 [nc addObserver:self selector:@selector(_requireClassDescriptionForClass:)
78 name:@"EOClassDescriptionNeededForClass" object:nil];
80 selector:@selector(_requireClassDescriptionForEntityName:)
81 name:@"EOClassDescriptionNeededForEntityName" object:nil];
83 self->entities = [[NSArray alloc] init];
84 self->entitiesByName = [[NSMutableDictionary alloc] initWithCapacity:4];
85 self->entitiesByClassName =
86 [[NSMutableDictionary alloc] initWithCapacity:4];
92 - (void)resetEntities {
93 [self->entities makeObjectsPerformSelector:@selector(resetModel)];
97 [[NSNotificationCenter defaultCenter] removeObserver:self];
99 RELEASE(self->entities);
100 RELEASE(self->entitiesByName);
101 RELEASE(self->entitiesByClassName);
104 RELEASE(self->adaptorName);
105 RELEASE(self->adaptorClassName);
106 RELEASE(self->connectionDictionary);
107 RELEASE(self->pkeyGeneratorDictionary);
108 RELEASE(self->userDictionary);
112 - (id)initWithContentsOfFile:(NSString*)filename
114 NSDictionary *propList;
116 propList = [[[NSDictionary alloc]
117 initWithContentsOfFile:filename] autorelease];
118 if (propList == nil) {
119 [NSException raise:NSInvalidArgumentException
120 format:@"EOModel: Couldn't load model file: %@", filename];
123 if ((self = [self initWithPropertyList:propList])) {
124 self->path = [filename copy];
125 self->name = [[[filename lastPathComponent] stringByDeletingPathExtension]
131 - (id)initWithPropertyList:(id)propertyList {
132 if ((self = [self init]) != nil) {
135 NSArray *propListEntities;
137 if (propertyList == nil) {
138 [NSException raise:NSInvalidArgumentException
140 @"EOModel: Argument of initWithPropertyList: must "
141 @"not be the nil object"];
143 if (![(dict = propertyList) isKindOfClass:[NSDictionary class]]) {
144 [NSException raise:NSInvalidArgumentException
145 format:@"EOModel: Argument of initWithPropertyList: must "
146 @"be kind of NSDictionary class"];
149 self->adaptorName = [[dict objectForKey:@"adaptorName"] copy];
150 self->adaptorClassName = [[dict objectForKey:@"adaptorClassName"] copy];
151 self->connectionDictionary =
152 [[dict objectForKey:@"connectionDictionary"] copy];
153 self->pkeyGeneratorDictionary =
154 [[dict objectForKey:@"pkeyGeneratorDictionary"] copy];
155 self->userDictionary = [[dict objectForKey:@"userDictionary"] copy];
157 propListEntities = [dict objectForKey:@"entities"];
160 [self setCreateMutableObjects:YES];
161 count = [propListEntities count];
162 for (i = 0; i < count; i++) {
165 entity = [EOEntity entityFromPropertyList:
166 [propListEntities objectAtIndex:i]
168 [self addEntity:entity];
171 count = [self->entities count];
172 for (i = 0; i < count; i++)
173 [[self->entities objectAtIndex:i] replaceStringsWithObjects];
175 /* Init relationships */
176 for (i = 0; i < count; i++) {
180 entity = [self->entities objectAtIndex:i];
181 rels = [entity relationships];
182 /* Replace all the strings in relationships. */
183 [rels makeObjectsPerformSelector:@selector(replaceStringsWithObjects)];
186 /* Another pass to allow properly initialization of flattened
188 for (i = 0; i < count; i++) {
190 [self->entities objectAtIndex:i];
191 NSArray* rels = [entity relationships];
193 [rels makeObjectsPerformSelector:@selector(initFlattenedRelationship)];
196 /* Init attributes */
197 for (i = 0; i < count; i++) {
198 EOEntity *entity = [self->entities objectAtIndex:i];
199 NSArray *attrs = [entity attributes];
201 [attrs makeObjectsPerformSelector:@selector(replaceStringsWithObjects)];
204 [self setCreateMutableObjects:NO];
206 return flags.errors ? (void)AUTORELEASE(self), (id)nil : (id)self;
209 - (id)initWithName:(NSString*)_name {
210 if ((self = [self init])) {
211 ASSIGN(self->name, _name);
216 /* class-description notifications */
218 - (void)_requireClassDescriptionForEntityName:(NSNotification *)_notification {
219 NSString *entityName;
221 if ((entityName = [_notification object])) {
224 if ((entity = [self->entitiesByName objectForKey:entityName])) {
225 EOClassDescription *d;
227 d = [[EOEntityClassDescription alloc] initWithEntity:entity];
228 [EOClassDescription registerClassDescription:d
229 forClass:NSClassFromString([entity className])];
234 - (void)_requireClassDescriptionForClass:(NSNotification *)_notification {
238 EOClassDescription *d;
240 if ((clazz = [_notification object]) == nil)
242 if ((className = NSStringFromClass(clazz)) == nil)
244 if ((entity = [self->entitiesByClassName objectForKey:className]) == nil)
247 d = [[EOEntityClassDescription alloc] initWithEntity:entity];
248 [EOClassDescription registerClassDescription:d forClass:clazz];
249 [d release]; d = nil;
254 - (id)modelAsPropertyList {
255 NSMutableDictionary *model = [NSMutableDictionary dictionaryWithCapacity:64];
258 [model setObject:[[NSNumber numberWithInt:[isa version]] stringValue]
259 forKey:@"EOModelVersion"];
261 [model setObject:name forKey:@"name"];
263 [model setObject:adaptorName forKey:@"adaptorName"];
264 if (adaptorClassName)
265 [model setObject:adaptorClassName forKey:@"adaptorClassName"];
266 if (connectionDictionary)
267 [model setObject:connectionDictionary forKey:@"connectionDictionary"];
268 if (pkeyGeneratorDictionary) {
269 [model setObject:pkeyGeneratorDictionary
270 forKey:@"pkeyGeneratorDictionary"];
273 [model setObject:userDictionary forKey:@"userDictionary"];
274 if (self->entities && (count = [self->entities count])) {
275 id entitiesArray = [NSMutableArray arrayWithCapacity:count];
277 [model setObject:entitiesArray forKey:@"entities"];
278 for (i = 0; i < count; i++) {
279 [entitiesArray addObject:
280 [[entities objectAtIndex:i] propertyList]];
287 - (BOOL)addEntity:(EOEntity *)entity {
288 NSString * entityName = [entity name];
290 if ([self->entitiesByName objectForKey:entityName])
293 if ([self createsMutableObjects])
294 [(NSMutableArray*)self->entities addObject:entity];
297 [[[self->entities autorelease] mutableCopy] autorelease];
298 [(NSMutableArray *)self->entities addObject:entity];
299 self->entities = [self->entities copy];
302 [self->entitiesByName setObject:entity forKey:entityName];
303 [self->entitiesByClassName setObject:entity forKey:[entity className]];
304 [entity setModel:self];
308 - (void)removeEntityNamed:(NSString*)entityName {
311 if (entityName == nil)
314 entity = [self->entitiesByName objectForKey:entityName];
316 if ([self createsMutableObjects])
317 [(NSMutableArray*)self->entities removeObject:entity];
319 self->entities = [AUTORELEASE(self->entities) mutableCopy];
320 [(NSMutableArray*)self->entities removeObject:entity];
321 self->entities = [AUTORELEASE(self->entities) copy];
323 [self->entitiesByName removeObjectForKey:entityName];
327 - (EOEntity *)entityNamed:(NSString *)entityName {
328 return [self->entitiesByName objectForKey:entityName];
331 - (NSArray *)referencesToProperty:property {
332 [self notImplemented:_cmd];
336 - (EOEntity *)entityForObject:object {
339 className = NSStringFromClass([object class]);
340 return [self->entitiesByClassName objectForKey:className];
343 - (BOOL)incorporateModel:(EOModel*)model {
344 [self notImplemented:_cmd];
348 - (void)setAdaptorName:(NSString*)_adaptorName {
349 id tmp = self->adaptorName;
350 self->adaptorName = [_adaptorName copyWithZone:[self zone]];
351 RELEASE(tmp); tmp = nil;
353 - (NSString *)adaptorName {
354 return self->adaptorName;
357 - (void)setAdaptorClassName:(NSString*)_adaptorClassName {
358 id tmp = self->adaptorClassName;
359 self->adaptorClassName = [_adaptorClassName copyWithZone:[self zone]];
360 RELEASE(tmp); tmp = nil;
362 - (NSString *)adaptorClassName {
363 return self->adaptorClassName;
366 - (void)setConnectionDictionary:(NSDictionary*)_connectionDictionary {
367 ASSIGN(self->connectionDictionary, _connectionDictionary);
369 - (NSDictionary *)connectionDictionary {
370 return self->connectionDictionary;
373 - (void)setPkeyGeneratorDictionary:(NSDictionary *)_dict {
374 ASSIGN(self->pkeyGeneratorDictionary, _dict);
376 - (NSDictionary *)pkeyGeneratorDictionary {
377 return self->pkeyGeneratorDictionary;
380 - (void)setUserDictionary:(NSDictionary *)_userDictionary {
381 ASSIGN(self->userDictionary, _userDictionary);
383 - (NSDictionary *)userDictionary {
384 return self->userDictionary;
393 - (NSArray *)entities {
394 NSMutableArray *ents;
397 cnt = [self->entities count];
398 ents = [NSMutableArray arrayWithCapacity:cnt];
399 for (i = 0; i < cnt; i++)
400 [ents addObject:[self->entities objectAtIndex:i]];
411 - (NSString *)description {
415 ms = [NSMutableString stringWithCapacity:256];
416 [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
418 if ((s = [self name])) [ms appendFormat:@" name=%@", s];
419 if ((s = [self path])) [ms appendFormat:@" path=%@", s];
420 if ((s = [self adaptorName])) [ms appendFormat:@" adaptor=%@", s];
421 if ((s = [self adaptorClassName])) [ms appendFormat:@" adaptor-class=%@", s];
423 [ms appendFormat:@" #entities=%d", [self->entities count]];
425 [ms appendString:@">"];
432 @implementation EOModel (EOModelPrivate)
434 - (void)setCreateMutableObjects:(BOOL)flag {
435 if(flags.createsMutableObjects == flag)
438 flags.createsMutableObjects = flag;
440 if(flags.createsMutableObjects)
441 self->entities = [AUTORELEASE(self->entities) mutableCopy];
443 self->entities = [AUTORELEASE(self->entities) copy];
446 - (BOOL)createsMutableObjects {
447 return flags.createsMutableObjects;
449 - (void)errorInReading {
453 @end /* EOModel (EOModelPrivate) */
455 @implementation EOModel(NewInEOF2)
457 - (void)loadAllModelObjects {