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:(NSDictionary *)propertyList {
132 if ((self = [self init])) {
134 NSArray *propListEntities;
136 if (propertyList == nil) {
137 [NSException raise:NSInvalidArgumentException
139 @"EOModel: Argument of initWithPropertyList: must "
140 @"not be the nil object"];
142 if (![propertyList isKindOfClass:[NSDictionary class]]) {
143 [NSException raise:NSInvalidArgumentException
144 format:@"EOModel: Argument of initWithPropertyList: must "
145 @"be kind of NSDictionary class"];
149 [[propertyList objectForKey:@"adaptorName"] copy];
150 self->adaptorClassName =
151 [[propertyList objectForKey:@"adaptorClassName"] copy];
152 self->connectionDictionary =
153 [[propertyList objectForKey:@"connectionDictionary"] copy];
154 self->pkeyGeneratorDictionary =
155 [[propertyList objectForKey:@"pkeyGeneratorDictionary"] copy];
156 self->userDictionary =
157 [[propertyList objectForKey:@"userDictionary"] copy];
159 propListEntities = [propertyList objectForKey:@"entities"];
162 [self setCreateMutableObjects:YES];
163 count = [propListEntities count];
164 for (i = 0; i < count; i++) {
167 entity = [EOEntity entityFromPropertyList:
168 [propListEntities objectAtIndex:i]
170 [self addEntity:entity];
173 count = [self->entities count];
174 for (i = 0; i < count; i++)
175 [[self->entities objectAtIndex:i] replaceStringsWithObjects];
177 /* Init relationships */
178 for (i = 0; i < count; i++) {
182 entity = [self->entities objectAtIndex:i];
183 rels = [entity relationships];
184 /* Replace all the strings in relationships. */
185 [rels makeObjectsPerformSelector:@selector(replaceStringsWithObjects)];
188 /* Another pass to allow properly initialization of flattened
190 for (i = 0; i < count; i++) {
192 [self->entities objectAtIndex:i];
193 NSArray* rels = [entity relationships];
195 [rels makeObjectsPerformSelector:@selector(initFlattenedRelationship)];
198 /* Init attributes */
199 for (i = 0; i < count; i++) {
200 EOEntity *entity = [self->entities objectAtIndex:i];
201 NSArray *attrs = [entity attributes];
203 [attrs makeObjectsPerformSelector:@selector(replaceStringsWithObjects)];
206 [self setCreateMutableObjects:NO];
208 return flags.errors ? (void)AUTORELEASE(self), (id)nil : self;
211 - (id)initWithName:(NSString*)_name {
212 if ((self = [self init])) {
213 ASSIGN(self->name, _name);
218 /* class-description notifications */
220 - (void)_requireClassDescriptionForEntityName:(NSNotification *)_notification {
221 NSString *entityName;
223 if ((entityName = [_notification object])) {
226 if ((entity = [self->entitiesByName objectForKey:entityName])) {
227 EOClassDescription *d;
229 d = [[EOEntityClassDescription alloc] initWithEntity:entity];
230 [EOClassDescription registerClassDescription:d
231 forClass:NSClassFromString([entity className])];
236 - (void)_requireClassDescriptionForClass:(NSNotification *)_notification {
240 EOClassDescription *d;
242 if ((clazz = [_notification object]) == nil)
244 if ((className = NSStringFromClass(clazz)) == nil)
246 if ((entity = [self->entitiesByClassName objectForKey:className]) == nil)
249 d = [[EOEntityClassDescription alloc] initWithEntity:entity];
250 [EOClassDescription registerClassDescription:d forClass:clazz];
251 [d release]; d = nil;
256 - (id)modelAsPropertyList {
257 NSMutableDictionary *model = [NSMutableDictionary dictionaryWithCapacity:64];
260 [model setObject:[[NSNumber numberWithInt:[isa version]] stringValue]
261 forKey:@"EOModelVersion"];
263 [model setObject:name forKey:@"name"];
265 [model setObject:adaptorName forKey:@"adaptorName"];
266 if (adaptorClassName)
267 [model setObject:adaptorClassName forKey:@"adaptorClassName"];
268 if (connectionDictionary)
269 [model setObject:connectionDictionary forKey:@"connectionDictionary"];
270 if (pkeyGeneratorDictionary) {
271 [model setObject:pkeyGeneratorDictionary
272 forKey:@"pkeyGeneratorDictionary"];
275 [model setObject:userDictionary forKey:@"userDictionary"];
276 if (self->entities && (count = [self->entities count])) {
277 id entitiesArray = [NSMutableArray arrayWithCapacity:count];
279 [model setObject:entitiesArray forKey:@"entities"];
280 for (i = 0; i < count; i++) {
281 [entitiesArray addObject:
282 [[entities objectAtIndex:i] propertyList]];
289 - (BOOL)addEntity:(EOEntity *)entity {
290 NSString * entityName = [entity name];
292 if ([self->entitiesByName objectForKey:entityName])
295 if ([self createsMutableObjects])
296 [(NSMutableArray*)self->entities addObject:entity];
299 [[[self->entities autorelease] mutableCopy] autorelease];
300 [(NSMutableArray *)self->entities addObject:entity];
301 self->entities = [self->entities copy];
304 [self->entitiesByName setObject:entity forKey:entityName];
305 [self->entitiesByClassName setObject:entity forKey:[entity className]];
306 [entity setModel:self];
310 - (void)removeEntityNamed:(NSString*)entityName {
313 if (entityName == nil)
316 entity = [self->entitiesByName objectForKey:entityName];
318 if ([self createsMutableObjects])
319 [(NSMutableArray*)self->entities removeObject:entity];
321 self->entities = [AUTORELEASE(self->entities) mutableCopy];
322 [(NSMutableArray*)self->entities removeObject:entity];
323 self->entities = [AUTORELEASE(self->entities) copy];
325 [self->entitiesByName removeObjectForKey:entityName];
329 - (EOEntity *)entityNamed:(NSString *)entityName {
330 return [self->entitiesByName objectForKey:entityName];
333 - (NSArray *)referencesToProperty:property {
334 [self notImplemented:_cmd];
338 - (EOEntity *)entityForObject:object {
341 className = NSStringFromClass([object class]);
342 return [self->entitiesByClassName objectForKey:className];
345 - (BOOL)incorporateModel:(EOModel*)model {
346 [self notImplemented:_cmd];
350 - (void)setAdaptorName:(NSString*)_adaptorName {
351 id tmp = self->adaptorName;
352 self->adaptorName = [_adaptorName copyWithZone:[self zone]];
353 RELEASE(tmp); tmp = nil;
355 - (NSString *)adaptorName {
356 return self->adaptorName;
359 - (void)setAdaptorClassName:(NSString*)_adaptorClassName {
360 id tmp = self->adaptorClassName;
361 self->adaptorClassName = [_adaptorClassName copyWithZone:[self zone]];
362 RELEASE(tmp); tmp = nil;
364 - (NSString *)adaptorClassName {
365 return self->adaptorClassName;
368 - (void)setConnectionDictionary:(NSDictionary*)_connectionDictionary {
369 ASSIGN(self->connectionDictionary, _connectionDictionary);
371 - (NSDictionary *)connectionDictionary {
372 return self->connectionDictionary;
375 - (void)setPkeyGeneratorDictionary:(NSDictionary *)_dict {
376 ASSIGN(self->pkeyGeneratorDictionary, _dict);
378 - (NSDictionary *)pkeyGeneratorDictionary {
379 return self->pkeyGeneratorDictionary;
382 - (void)setUserDictionary:(NSDictionary *)_userDictionary {
383 ASSIGN(self->userDictionary, _userDictionary);
385 - (NSDictionary *)userDictionary {
386 return self->userDictionary;
395 - (NSArray *)entities {
396 NSMutableArray *ents;
399 cnt = [self->entities count];
400 ents = [NSMutableArray arrayWithCapacity:cnt];
401 for (i = 0; i < cnt; i++)
402 [ents addObject:[self->entities objectAtIndex:i]];
413 - (NSString *)description {
417 ms = [NSMutableString stringWithCapacity:256];
418 [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
420 if ((s = [self name])) [ms appendFormat:@" name=%@", s];
421 if ((s = [self path])) [ms appendFormat:@" path=%@", s];
422 if ((s = [self adaptorName])) [ms appendFormat:@" adaptor=%@", s];
423 if ((s = [self adaptorClassName])) [ms appendFormat:@" adaptor-class=%@", s];
425 [ms appendFormat:@" #entities=%d", [self->entities count]];
427 [ms appendString:@">"];
434 @implementation EOModel (EOModelPrivate)
436 - (void)setCreateMutableObjects:(BOOL)flag {
437 if(flags.createsMutableObjects == flag)
440 flags.createsMutableObjects = flag;
442 if(flags.createsMutableObjects)
443 self->entities = [AUTORELEASE(self->entities) mutableCopy];
445 self->entities = [AUTORELEASE(self->entities) copy];
448 - (BOOL)createsMutableObjects {
449 return flags.createsMutableObjects;
451 - (void)errorInReading {
455 @end /* EOModel (EOModelPrivate) */
457 @implementation EOModel(NewInEOF2)
459 - (void)loadAllModelObjects {