]> err.no Git - sope/blob - sope-gdl1/GDLAccess/EOModel.m
renamed PostgreSQL72 to PostgreSQL, install in Library/GDLAdaptors-1.1
[sope] / sope-gdl1 / GDLAccess / EOModel.m
1 /* 
2    EOModel.m
3
4    Copyright (C) 1996 Free Software Foundation, Inc.
5
6    Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
7    Date: August 1996
8
9    This file is part of the GNUstep Database Library.
10
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.
15
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.
20
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.
25 */
26
27 #import "common.h"
28 #import "EOModel.h"
29 #import "EOEntity.h"
30
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... */
35 #if 0
36 #  import "EOCustomValues.m"
37 #endif
38
39 void EOModel_linkCategories(void) {
40   void EOAccess_EOCustomValues_link(void);
41
42   EOAccess_EOCustomValues_link();
43 }
44
45 @implementation EOModel
46
47 - (id)copyWithZone:(NSZone *)_zone {
48   return RETAIN(self);
49 }
50
51 + (NSString*)findPathForModelNamed:(NSString*)modelName {
52     int i;
53     NSBundle* bundle = [NSBundle mainBundle];
54     NSString* modelPath = [bundle pathForResource:modelName ofType:@"eomodel"];
55     NSString* paths[] = { @"~/Library/Models",
56                           @"/LocalLibrary/Models",
57                           @"/NextLibrary/Models",
58                           nil };
59
60     if(modelPath)
61         return modelPath;
62
63     for(i = 0; paths[i]; i++) {
64         bundle = [NSBundle bundleWithPath:paths[i]];
65         modelPath = [bundle pathForResource:modelName ofType:@"eomodel"];
66         if(modelPath)
67             return modelPath;
68     }
69     return nil;
70 }
71
72 - (id)init {
73   if ((self = [super init])) {
74     NSNotificationCenter *nc;
75
76     nc = [NSNotificationCenter defaultCenter];
77     [nc addObserver:self selector:@selector(_requireClassDescriptionForClass:)
78         name:@"EOClassDescriptionNeededForClass" object:nil];
79     [nc addObserver:self 
80         selector:@selector(_requireClassDescriptionForEntityName:)
81         name:@"EOClassDescriptionNeededForEntityName" object:nil];
82     
83     self->entities       = [[NSArray alloc] init];
84     self->entitiesByName = [[NSMutableDictionary alloc] initWithCapacity:4];
85     self->entitiesByClassName = 
86       [[NSMutableDictionary alloc] initWithCapacity:4];
87   }
88
89   return self;
90 }
91
92 - (void)resetEntities {
93   [self->entities makeObjectsPerformSelector:@selector(resetModel)];
94 }
95
96 - (void)dealloc {
97     [[NSNotificationCenter defaultCenter] removeObserver:self];
98     [self resetEntities];
99     RELEASE(self->entities);
100     RELEASE(self->entitiesByName);
101     RELEASE(self->entitiesByClassName);
102     RELEASE(self->name);
103     RELEASE(self->path);
104     RELEASE(self->adaptorName);
105     RELEASE(self->adaptorClassName);
106     RELEASE(self->connectionDictionary);
107     RELEASE(self->pkeyGeneratorDictionary);
108     RELEASE(self->userDictionary);
109     [super dealloc];
110 }
111
112 - (id)initWithContentsOfFile:(NSString*)filename
113 {
114   NSDictionary *propList;
115
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];
121   }
122  
123   if ((self = [self initWithPropertyList:propList])) {
124     self->path = [filename copy];
125     self->name = [[[filename lastPathComponent] stringByDeletingPathExtension]
126                              copy];
127   }
128   return self;
129 }
130
131 - (id)initWithPropertyList:(NSDictionary *)propertyList {
132   if ((self = [self init])) {
133     int     i, count;
134     NSArray *propListEntities;
135     
136     if (propertyList == nil) {
137       [NSException raise:NSInvalidArgumentException
138                    format:
139                      @"EOModel: Argument of initWithPropertyList: must "
140                      @"not be the nil object"];
141     }
142     if (![propertyList isKindOfClass:[NSDictionary class]]) {
143       [NSException raise:NSInvalidArgumentException
144                    format:@"EOModel: Argument of initWithPropertyList: must "
145                            @"be kind of NSDictionary class"];
146     }
147     
148     self->adaptorName =
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];
158     
159     propListEntities = [propertyList objectForKey:@"entities"];
160
161     flags.errors = NO;
162     [self setCreateMutableObjects:YES];
163     count = [propListEntities count];
164     for (i = 0; i < count; i++) {
165       EOEntity *entity;
166
167       entity = [EOEntity entityFromPropertyList:
168                            [propListEntities objectAtIndex:i]
169                          model:self];
170       [self addEntity:entity];
171     }
172
173     count = [self->entities count];
174     for (i = 0; i < count; i++)
175       [[self->entities objectAtIndex:i] replaceStringsWithObjects];
176
177     /* Init relationships */
178     for (i = 0; i < count; i++) {
179       EOEntity *entity;
180       NSArray  *rels;
181
182       entity = [self->entities objectAtIndex:i];
183       rels   = [entity relationships];
184       /* Replace all the strings in relationships. */
185       [rels makeObjectsPerformSelector:@selector(replaceStringsWithObjects)];
186     }
187
188     /* Another pass to allow properly initialization of flattened
189         relationships. */
190     for (i = 0; i < count; i++) {
191         EOEntity* entity =
192           [self->entities objectAtIndex:i];
193         NSArray* rels = [entity relationships];
194
195         [rels makeObjectsPerformSelector:@selector(initFlattenedRelationship)];
196     }
197
198     /* Init attributes */
199     for (i = 0; i < count; i++) {
200       EOEntity *entity = [self->entities objectAtIndex:i];
201       NSArray  *attrs  = [entity attributes];
202       
203       [attrs makeObjectsPerformSelector:@selector(replaceStringsWithObjects)];
204     }
205
206     [self setCreateMutableObjects:NO];
207   }
208   return flags.errors ? (void)AUTORELEASE(self), (id)nil : self;
209 }
210
211 - (id)initWithName:(NSString*)_name {
212   if ((self = [self init])) {
213     ASSIGN(self->name, _name);
214   }
215   return self;
216 }
217
218 /* class-description notifications */
219
220 - (void)_requireClassDescriptionForEntityName:(NSNotification *)_notification {
221   NSString *entityName;
222
223   if ((entityName = [_notification object])) {
224     EOEntity *entity;
225
226     if ((entity = [self->entitiesByName objectForKey:entityName])) {
227       EOClassDescription *d;
228
229       d = [[EOEntityClassDescription alloc] initWithEntity:entity];
230       [EOClassDescription registerClassDescription:d
231                           forClass:NSClassFromString([entity className])];
232       RELEASE(d); d = nil;
233     }
234   }
235 }
236 - (void)_requireClassDescriptionForClass:(NSNotification *)_notification {
237   Class    clazz;
238   NSString *className;
239   EOEntity *entity;
240   EOClassDescription *d;
241
242   if ((clazz = [_notification object]) == nil)
243     return;
244   if ((className = NSStringFromClass(clazz)) == nil)
245     return;
246   if ((entity = [self->entitiesByClassName objectForKey:className]) == nil)
247     return;
248
249   d = [[EOEntityClassDescription alloc] initWithEntity:entity];
250   [EOClassDescription registerClassDescription:d forClass:clazz];
251   [d release]; d = nil;
252 }
253
254 /* property list */
255
256 - (id)modelAsPropertyList {
257   NSMutableDictionary *model = [NSMutableDictionary dictionaryWithCapacity:64];
258   int i, count;
259     
260   [model setObject:[[NSNumber numberWithInt:[isa version]] stringValue]
261          forKey:@"EOModelVersion"];
262   if (name)
263         [model setObject:name forKey:@"name"];
264   if (adaptorName)
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"];
273   }
274   if (userDictionary)
275         [model setObject:userDictionary forKey:@"userDictionary"];
276   if (self->entities && (count = [self->entities count])) {
277     id entitiesArray = [NSMutableArray arrayWithCapacity:count];
278
279     [model setObject:entitiesArray forKey:@"entities"];
280     for (i = 0; i < count; i++) {
281       [entitiesArray addObject:
282                        [[entities objectAtIndex:i] propertyList]];
283     }
284   }
285
286   return model;
287 }
288
289 - (BOOL)addEntity:(EOEntity *)entity {
290   NSString * entityName = [entity name];
291
292   if ([self->entitiesByName objectForKey:entityName])
293         return NO;
294
295   if ([self createsMutableObjects])
296         [(NSMutableArray*)self->entities addObject:entity];
297   else {
298     self->entities =
299       [[[self->entities autorelease] mutableCopy] autorelease];
300     [(NSMutableArray *)self->entities addObject:entity];
301     self->entities = [self->entities copy];
302   }
303
304   [self->entitiesByName setObject:entity forKey:entityName];
305   [self->entitiesByClassName setObject:entity forKey:[entity className]];
306   [entity setModel:self];
307   return YES;
308 }
309
310 - (void)removeEntityNamed:(NSString*)entityName {
311   id entity;
312   
313   if (entityName == nil)
314     return;
315   
316   entity = [self->entitiesByName objectForKey:entityName];
317
318   if ([self createsMutableObjects])
319     [(NSMutableArray*)self->entities removeObject:entity];
320   else {
321     self->entities = [AUTORELEASE(self->entities) mutableCopy];
322     [(NSMutableArray*)self->entities removeObject:entity];
323     self->entities = [AUTORELEASE(self->entities) copy];
324   }
325   [self->entitiesByName removeObjectForKey:entityName];
326   [entity resetModel];
327 }
328
329 - (EOEntity *)entityNamed:(NSString *)entityName {
330   return [self->entitiesByName objectForKey:entityName];
331 }
332
333 - (NSArray *)referencesToProperty:property {
334   [self notImplemented:_cmd];
335   return 0;
336 }
337
338 - (EOEntity *)entityForObject:object {
339   NSString *className;
340
341   className = NSStringFromClass([object class]);
342   return [self->entitiesByClassName objectForKey:className];
343 }
344
345 - (BOOL)incorporateModel:(EOModel*)model {
346   [self notImplemented:_cmd];
347   return 0;
348 }
349
350 - (void)setAdaptorName:(NSString*)_adaptorName {
351   id tmp = self->adaptorName;
352   self->adaptorName = [_adaptorName copyWithZone:[self zone]];
353   RELEASE(tmp); tmp = nil;
354 }
355 - (NSString *)adaptorName {
356   return self->adaptorName;
357 }
358
359 - (void)setAdaptorClassName:(NSString*)_adaptorClassName {
360   id tmp = self->adaptorClassName;
361   self->adaptorClassName = [_adaptorClassName copyWithZone:[self zone]];
362   RELEASE(tmp); tmp = nil;
363 }
364 - (NSString *)adaptorClassName {
365   return self->adaptorClassName;
366 }
367
368 - (void)setConnectionDictionary:(NSDictionary*)_connectionDictionary {
369   ASSIGN(self->connectionDictionary, _connectionDictionary);
370 }
371 - (NSDictionary *)connectionDictionary {
372   return self->connectionDictionary;
373 }
374
375 - (void)setPkeyGeneratorDictionary:(NSDictionary *)_dict {
376   ASSIGN(self->pkeyGeneratorDictionary, _dict);
377 }
378 - (NSDictionary *)pkeyGeneratorDictionary {
379   return self->pkeyGeneratorDictionary;
380 }
381
382 - (void)setUserDictionary:(NSDictionary *)_userDictionary {
383   ASSIGN(self->userDictionary, _userDictionary);
384 }
385 - (NSDictionary *)userDictionary {
386   return self->userDictionary;
387 }
388
389 - (NSString *)path {
390   return self->path;
391 }
392 - (NSString *)name {
393   return self->name;
394 }
395 - (NSArray *)entities {
396   NSMutableArray *ents;
397   int cnt, i;
398
399   cnt  = [self->entities count];
400   ents = [NSMutableArray arrayWithCapacity:cnt];
401   for (i = 0; i < cnt; i++)
402     [ents addObject:[self->entities objectAtIndex:i]];
403   
404   return ents;
405 }
406
407 + (int)version {
408   return 1;
409 }
410
411 /* description */
412
413 - (NSString *)description {
414   NSMutableString *ms;
415   NSString *s;
416
417   ms = [NSMutableString stringWithCapacity:256];
418   [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
419
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];
424   
425   [ms appendFormat:@" #entities=%d", [self->entities count]];
426   
427   [ms appendString:@">"];
428   return ms;
429 }
430
431 @end /* EOModel */
432
433
434 @implementation EOModel (EOModelPrivate)
435
436 - (void)setCreateMutableObjects:(BOOL)flag {
437     if(flags.createsMutableObjects == flag)
438         return;
439
440     flags.createsMutableObjects = flag;
441
442     if(flags.createsMutableObjects)
443         self->entities = [AUTORELEASE(self->entities) mutableCopy];
444     else
445         self->entities = [AUTORELEASE(self->entities) copy];
446 }
447
448 - (BOOL)createsMutableObjects {
449   return flags.createsMutableObjects;
450 }
451 - (void)errorInReading {
452   flags.errors = YES;
453 }
454
455 @end /* EOModel (EOModelPrivate) */
456
457 @implementation EOModel(NewInEOF2)
458
459 - (void)loadAllModelObjects {
460 }
461
462 @end