]> err.no Git - sope/blob - sope-gdl1/GDLAccess/EOModel.m
added missing inline pathes
[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:(id)propertyList {
132   if ((self = [self init]) != nil) {
133     NSDictionary *dict;
134     int     i, count;
135     NSArray *propListEntities;
136     
137     if (propertyList == nil) {
138       [NSException raise:NSInvalidArgumentException
139                    format:
140                      @"EOModel: Argument of initWithPropertyList: must "
141                      @"not be the nil object"];
142     }
143     if (![(dict = propertyList) isKindOfClass:[NSDictionary class]]) {
144       [NSException raise:NSInvalidArgumentException
145                    format:@"EOModel: Argument of initWithPropertyList: must "
146                            @"be kind of NSDictionary class"];
147     }
148     
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];
156     
157     propListEntities = [dict objectForKey:@"entities"];
158
159     flags.errors = NO;
160     [self setCreateMutableObjects:YES];
161     count = [propListEntities count];
162     for (i = 0; i < count; i++) {
163       EOEntity *entity;
164
165       entity = [EOEntity entityFromPropertyList:
166                            [propListEntities objectAtIndex:i]
167                          model:self];
168       [self addEntity:entity];
169     }
170
171     count = [self->entities count];
172     for (i = 0; i < count; i++)
173       [[self->entities objectAtIndex:i] replaceStringsWithObjects];
174
175     /* Init relationships */
176     for (i = 0; i < count; i++) {
177       EOEntity *entity;
178       NSArray  *rels;
179
180       entity = [self->entities objectAtIndex:i];
181       rels   = [entity relationships];
182       /* Replace all the strings in relationships. */
183       [rels makeObjectsPerformSelector:@selector(replaceStringsWithObjects)];
184     }
185
186     /* Another pass to allow properly initialization of flattened
187         relationships. */
188     for (i = 0; i < count; i++) {
189         EOEntity* entity =
190           [self->entities objectAtIndex:i];
191         NSArray* rels = [entity relationships];
192
193         [rels makeObjectsPerformSelector:@selector(initFlattenedRelationship)];
194     }
195
196     /* Init attributes */
197     for (i = 0; i < count; i++) {
198       EOEntity *entity = [self->entities objectAtIndex:i];
199       NSArray  *attrs  = [entity attributes];
200       
201       [attrs makeObjectsPerformSelector:@selector(replaceStringsWithObjects)];
202     }
203
204     [self setCreateMutableObjects:NO];
205   }
206   return flags.errors ? (void)AUTORELEASE(self), (id)nil : self;
207 }
208
209 - (id)initWithName:(NSString*)_name {
210   if ((self = [self init])) {
211     ASSIGN(self->name, _name);
212   }
213   return self;
214 }
215
216 /* class-description notifications */
217
218 - (void)_requireClassDescriptionForEntityName:(NSNotification *)_notification {
219   NSString *entityName;
220
221   if ((entityName = [_notification object])) {
222     EOEntity *entity;
223
224     if ((entity = [self->entitiesByName objectForKey:entityName])) {
225       EOClassDescription *d;
226
227       d = [[EOEntityClassDescription alloc] initWithEntity:entity];
228       [EOClassDescription registerClassDescription:d
229                           forClass:NSClassFromString([entity className])];
230       RELEASE(d); d = nil;
231     }
232   }
233 }
234 - (void)_requireClassDescriptionForClass:(NSNotification *)_notification {
235   Class    clazz;
236   NSString *className;
237   EOEntity *entity;
238   EOClassDescription *d;
239
240   if ((clazz = [_notification object]) == nil)
241     return;
242   if ((className = NSStringFromClass(clazz)) == nil)
243     return;
244   if ((entity = [self->entitiesByClassName objectForKey:className]) == nil)
245     return;
246
247   d = [[EOEntityClassDescription alloc] initWithEntity:entity];
248   [EOClassDescription registerClassDescription:d forClass:clazz];
249   [d release]; d = nil;
250 }
251
252 /* property list */
253
254 - (id)modelAsPropertyList {
255   NSMutableDictionary *model = [NSMutableDictionary dictionaryWithCapacity:64];
256   int i, count;
257     
258   [model setObject:[[NSNumber numberWithInt:[isa version]] stringValue]
259          forKey:@"EOModelVersion"];
260   if (name)
261         [model setObject:name forKey:@"name"];
262   if (adaptorName)
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"];
271   }
272   if (userDictionary)
273         [model setObject:userDictionary forKey:@"userDictionary"];
274   if (self->entities && (count = [self->entities count])) {
275     id entitiesArray = [NSMutableArray arrayWithCapacity:count];
276
277     [model setObject:entitiesArray forKey:@"entities"];
278     for (i = 0; i < count; i++) {
279       [entitiesArray addObject:
280                        [[entities objectAtIndex:i] propertyList]];
281     }
282   }
283
284   return model;
285 }
286
287 - (BOOL)addEntity:(EOEntity *)entity {
288   NSString * entityName = [entity name];
289
290   if ([self->entitiesByName objectForKey:entityName])
291         return NO;
292
293   if ([self createsMutableObjects])
294         [(NSMutableArray*)self->entities addObject:entity];
295   else {
296     self->entities =
297       [[[self->entities autorelease] mutableCopy] autorelease];
298     [(NSMutableArray *)self->entities addObject:entity];
299     self->entities = [self->entities copy];
300   }
301
302   [self->entitiesByName setObject:entity forKey:entityName];
303   [self->entitiesByClassName setObject:entity forKey:[entity className]];
304   [entity setModel:self];
305   return YES;
306 }
307
308 - (void)removeEntityNamed:(NSString*)entityName {
309   id entity;
310   
311   if (entityName == nil)
312     return;
313   
314   entity = [self->entitiesByName objectForKey:entityName];
315
316   if ([self createsMutableObjects])
317     [(NSMutableArray*)self->entities removeObject:entity];
318   else {
319     self->entities = [AUTORELEASE(self->entities) mutableCopy];
320     [(NSMutableArray*)self->entities removeObject:entity];
321     self->entities = [AUTORELEASE(self->entities) copy];
322   }
323   [self->entitiesByName removeObjectForKey:entityName];
324   [entity resetModel];
325 }
326
327 - (EOEntity *)entityNamed:(NSString *)entityName {
328   return [self->entitiesByName objectForKey:entityName];
329 }
330
331 - (NSArray *)referencesToProperty:property {
332   [self notImplemented:_cmd];
333   return 0;
334 }
335
336 - (EOEntity *)entityForObject:object {
337   NSString *className;
338
339   className = NSStringFromClass([object class]);
340   return [self->entitiesByClassName objectForKey:className];
341 }
342
343 - (BOOL)incorporateModel:(EOModel*)model {
344   [self notImplemented:_cmd];
345   return 0;
346 }
347
348 - (void)setAdaptorName:(NSString*)_adaptorName {
349   id tmp = self->adaptorName;
350   self->adaptorName = [_adaptorName copyWithZone:[self zone]];
351   RELEASE(tmp); tmp = nil;
352 }
353 - (NSString *)adaptorName {
354   return self->adaptorName;
355 }
356
357 - (void)setAdaptorClassName:(NSString*)_adaptorClassName {
358   id tmp = self->adaptorClassName;
359   self->adaptorClassName = [_adaptorClassName copyWithZone:[self zone]];
360   RELEASE(tmp); tmp = nil;
361 }
362 - (NSString *)adaptorClassName {
363   return self->adaptorClassName;
364 }
365
366 - (void)setConnectionDictionary:(NSDictionary*)_connectionDictionary {
367   ASSIGN(self->connectionDictionary, _connectionDictionary);
368 }
369 - (NSDictionary *)connectionDictionary {
370   return self->connectionDictionary;
371 }
372
373 - (void)setPkeyGeneratorDictionary:(NSDictionary *)_dict {
374   ASSIGN(self->pkeyGeneratorDictionary, _dict);
375 }
376 - (NSDictionary *)pkeyGeneratorDictionary {
377   return self->pkeyGeneratorDictionary;
378 }
379
380 - (void)setUserDictionary:(NSDictionary *)_userDictionary {
381   ASSIGN(self->userDictionary, _userDictionary);
382 }
383 - (NSDictionary *)userDictionary {
384   return self->userDictionary;
385 }
386
387 - (NSString *)path {
388   return self->path;
389 }
390 - (NSString *)name {
391   return self->name;
392 }
393 - (NSArray *)entities {
394   NSMutableArray *ents;
395   int cnt, i;
396
397   cnt  = [self->entities count];
398   ents = [NSMutableArray arrayWithCapacity:cnt];
399   for (i = 0; i < cnt; i++)
400     [ents addObject:[self->entities objectAtIndex:i]];
401   
402   return ents;
403 }
404
405 + (int)version {
406   return 1;
407 }
408
409 /* description */
410
411 - (NSString *)description {
412   NSMutableString *ms;
413   NSString *s;
414
415   ms = [NSMutableString stringWithCapacity:256];
416   [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
417
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];
422   
423   [ms appendFormat:@" #entities=%d", [self->entities count]];
424   
425   [ms appendString:@">"];
426   return ms;
427 }
428
429 @end /* EOModel */
430
431
432 @implementation EOModel (EOModelPrivate)
433
434 - (void)setCreateMutableObjects:(BOOL)flag {
435     if(flags.createsMutableObjects == flag)
436         return;
437
438     flags.createsMutableObjects = flag;
439
440     if(flags.createsMutableObjects)
441         self->entities = [AUTORELEASE(self->entities) mutableCopy];
442     else
443         self->entities = [AUTORELEASE(self->entities) copy];
444 }
445
446 - (BOOL)createsMutableObjects {
447   return flags.createsMutableObjects;
448 }
449 - (void)errorInReading {
450   flags.errors = YES;
451 }
452
453 @end /* EOModel (EOModelPrivate) */
454
455 @implementation EOModel(NewInEOF2)
456
457 - (void)loadAllModelObjects {
458 }
459
460 @end