]> err.no Git - sope/blob - skyrix-xml/SaxObjC/SaxObjectModel.m
added svn:keywords and svn:ignore where appropriate. removed CVS artifacts.
[sope] / skyrix-xml / SaxObjC / SaxObjectModel.m
1 /*
2   Copyright (C) 2000-2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include "SaxObjectModel.h"
24 #include "common.h"
25
26 static NSDictionary *mapDictsToObjects(NSDictionary *_dict, Class clazz) {
27   NSMutableDictionary *md;
28   NSEnumerator *e;
29   NSString     *key;
30   
31   md = [NSMutableDictionary dictionaryWithCapacity:16];
32   
33   e = [_dict keyEnumerator];
34   while ((key = [e nextObject])) {
35     id obj;
36
37     obj = [[clazz alloc] initWithDictionary:[_dict objectForKey:key]];
38     [md setObject:obj forKey:key];
39     [obj release];
40   }
41   return md;
42 }
43
44 @implementation SaxObjectModel
45
46 static BOOL    doDebug = NO;
47 static NSArray *searchPathes = nil;
48
49 + (NSArray *)saxMappingSearchPathes {
50   if (searchPathes == nil) {
51     NSMutableArray *ma;
52     NSDictionary   *env;
53     id tmp;
54     
55     env = [[NSProcessInfo processInfo] environment];
56     ma  = [NSMutableArray arrayWithCapacity:6];
57
58 #if COCOA_Foundation_LIBRARY
59     tmp = NSSearchPathForDirectoriesInDomains(NSAllLibrariesDirectory,
60                                               NSAllDomainsMask,
61                                               YES);
62     if ([tmp count] > 0) {
63       NSEnumerator *e;
64       
65       e = [tmp objectEnumerator];
66       while ((tmp = [e nextObject])) {
67         tmp = [tmp stringByAppendingPathComponent:@"SaxMappings"];
68         if (![ma containsObject:tmp])
69           [ma addObject:tmp];
70       }
71     }
72 #else
73     if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil)
74       tmp = [env objectForKey:@"GNUSTEP_PATHLIST"];
75     tmp = [tmp componentsSeparatedByString:@":"];
76     if ([tmp count] > 0) {
77       NSEnumerator *e;
78       
79       e = [tmp objectEnumerator];
80       while ((tmp = [e nextObject])) {
81         tmp = [tmp stringByAppendingPathComponent:@"Library/SaxMappings"];
82         if (![ma containsObject:tmp])
83           [ma addObject:tmp];
84       }
85     }
86     else {
87       NSLog(@"%s: empty library search path !", __PRETTY_FUNCTION__);
88     }
89 #endif
90     
91     searchPathes = [ma copy];
92     
93     if ([searchPathes count] == 0)
94       NSLog(@"%s: no search pathes were found !", __PRETTY_FUNCTION__);
95   }
96   return searchPathes;
97 }
98
99 + (id)modelWithName:(NSString *)_name {
100   NSFileManager *fileManager;
101   NSEnumerator  *pathes;
102   NSString      *path;
103
104   /* first look in main bundle */
105   
106   if ((path = [[NSBundle mainBundle] pathForResource:_name ofType:@"xmap"]))
107     return [self modelWithContentsOfFile:path];
108
109   /* then in Library */
110   
111   fileManager = [NSFileManager defaultManager];
112   pathes      = [[[self class] saxMappingSearchPathes] objectEnumerator];
113   _name       = [_name stringByAppendingPathExtension:@"xmap"];
114   
115   while ((path = [pathes nextObject])) {
116     BOOL isDir;
117     
118     path = [path stringByAppendingPathComponent:_name];
119     
120     if (![fileManager fileExistsAtPath:path isDirectory:&isDir])
121       continue;
122     if (isDir)
123       continue;
124     
125     break;
126   }
127   
128   return [self modelWithContentsOfFile:path];
129 }
130
131 + (id)modelWithContentsOfFile:(NSString *)_path {
132   NSDictionary *dict;
133   
134   if ((dict = [NSDictionary dictionaryWithContentsOfFile:_path]) == nil)
135     return nil;
136   
137   return [[[self alloc] initWithDictionary:dict] autorelease];
138 }
139
140 - (id)initWithDictionary:(NSDictionary *)_dict {
141   self->nsToModel =
142     [mapDictsToObjects(_dict, [SaxNamespaceModel class]) retain];
143   return self;
144 }
145
146 - (void)dealloc {
147   [self->nsToModel release];
148   [super dealloc];
149 }
150
151 /* queries */
152
153 - (SaxTagModel *)modelForTag:(NSString *)_localName namespace:(NSString *)_ns {
154   SaxNamespaceModel *nsmap;
155   
156   if ((nsmap = [self->nsToModel objectForKey:_ns]) == nil) {
157     if ((nsmap = [self->nsToModel objectForKey:@"*"]) == nil)
158       return nil;
159   }
160   return [nsmap modelForTag:_localName];
161 }
162
163 /* faking dictionary */
164
165 - (id)objectForKey:(id)_key {
166   return [self->nsToModel objectForKey:_key];
167 }
168
169 @end /* SaxMappingModel */
170
171 @implementation SaxNamespaceModel
172
173 - (id)initWithDictionary:(NSDictionary *)_dict {
174   self->tagToModel = [mapDictsToObjects(_dict, [SaxTagModel class]) retain];
175   return self;
176 }
177
178 - (void)dealloc {
179   [self->tagToModel release];
180   [super dealloc];
181 }
182
183 /* queries */
184
185 - (SaxTagModel *)modelForTag:(NSString *)_localName {
186   SaxTagModel *map;
187   
188   if ((map = [self->tagToModel objectForKey:_localName]))
189     return map;
190   if ((map = [self->tagToModel objectForKey:@"*"]))
191     return map;
192   return nil;
193 }
194
195 /* faking dictionary */
196
197 - (id)objectForKey:(id)_key {
198   return [self->tagToModel objectForKey:_key];
199 }
200
201 @end /* SaxNamespaceModel */
202
203 @implementation SaxTagModel
204
205 - (NSDictionary *)_extractAttributeMapping:(NSDictionary *)as {
206   NSMutableDictionary *md;
207   NSEnumerator *keys;
208   NSString     *k;
209   NSDictionary *result;
210       
211   md = [[NSMutableDictionary alloc] initWithCapacity:16];
212       
213   keys = [as keyEnumerator];
214   while ((k = [keys nextObject])) {
215     id val;
216         
217     val = [as objectForKey:k];
218         
219     if ([val isKindOfClass:[NSString class]])
220       [md setObject:val forKey:k];
221     else if ([val count] == 0)
222       [md setObject:k forKey:k];
223     else 
224       [md setObject:[(NSDictionary *)val objectForKey:@"key"] forKey:k];
225   }
226   
227   result = [md copy];
228   [md release];
229   return result;
230 }
231
232 - (id)initWithDictionary:(NSDictionary *)_dict {
233   if ((self = [super init])) {
234     NSDictionary *rels;
235     NSDictionary *as;
236     
237     self->className     = [[_dict objectForKey:@"class"]  copy];
238     self->key           = [[_dict objectForKey:@"key"]    copy];
239     self->tagKey        = [[_dict objectForKey:@"tagKey"] copy];
240     self->namespaceKey  = [[_dict objectForKey:@"namespaceKey"] copy];
241     self->parentKey     = [[_dict objectForKey:@"parentKey"] copy];
242     self->contentKey    = [[_dict objectForKey:@"contentKey"] copy];
243     self->defaultValues = [[_dict objectForKey:@"defaultValues"] copy];
244     
245     if ((as = [_dict objectForKey:@"attributes"]))
246       self->attrToKey = [self _extractAttributeMapping:as];
247     
248     if ((rels = [_dict objectForKey:@"ToManyRelationships"])) {
249       NSMutableDictionary *md;
250       NSEnumerator *keys;
251       NSString *k;
252       
253       self->toManyRelationshipKeys = [[rels allKeys] copy];
254     
255       md = [[NSMutableDictionary alloc] initWithCapacity:16];
256       
257       keys = [self->toManyRelationshipKeys objectEnumerator];
258       while ((k = [keys nextObject])) {
259         id       tags;
260         NSString *tag;
261         
262         tags = [rels objectForKey:k];
263         if ([tags isKindOfClass:[NSString class]])
264           tags = [NSArray arrayWithObject:tags];
265         tags = [tags objectEnumerator];
266         
267         while ((tag = [tags nextObject])) {
268           NSString *t;
269           
270           if ((t = [md objectForKey:tag])) {
271             NSLog(@"SaxObjectModel: cannot map tag '%@' to key '%@', "
272                   @"it is already mapped to key '%@'.",
273                   tag, k, t);
274           }
275           else {
276             [md setObject:k forKey:tag];
277           }
278         }
279       }
280       self->tagToKey = [md copy];
281       [md release];
282     }
283     
284   }
285   return self;
286 }
287
288 - (void)dealloc {
289   [self->defaultValues          release];
290   [self->toManyRelationshipKeys release];
291   [self->tagToKey     release];
292   [self->className    release];
293   [self->tagKey       release];
294   [self->namespaceKey release];
295   [self->parentKey  release];
296   [self->contentKey release];
297   [self->key        release];
298   [self->attrToKey  release];
299   [super dealloc];
300 }
301
302 /* accessors */
303
304 - (NSString *)className {
305   return self->className;
306 }
307 - (NSString *)key {
308   return self->key;
309 }
310 - (NSString *)tagKey {
311   return self->tagKey;
312 }
313 - (NSString *)namespaceKey {
314   return self->namespaceKey;
315 }
316 - (NSString *)parentKey {
317   return self->parentKey;
318 }
319 - (NSString *)contentKey {
320   return self->contentKey;
321 }
322
323 - (NSDictionary *)defaultValues {
324   return self->defaultValues;
325 }
326
327 - (BOOL)isToManyKey:(NSString *)_key {
328   return [self->toManyRelationshipKeys containsObject:_key];
329 }
330 - (NSArray *)toManyRelationshipKeys {
331   return self->toManyRelationshipKeys;
332 }
333
334 - (BOOL)isToManyTag:(NSString *)_tag {
335   return ([self->tagToKey objectForKey:_tag] != nil) ? YES : NO;
336 }
337
338 - (NSString *)propertyKeyForChildTag:(NSString *)_tag {
339   return [self->tagToKey objectForKey:_tag];
340 }
341
342 - (NSArray *)attributeKeys {
343   return [self->attrToKey allKeys];
344 }
345 - (NSString *)propertyKeyForAttribute:(NSString *)_attr {
346   return [self->attrToKey objectForKey:_attr];
347 }
348
349 /* object operations */
350
351 - (void)addValue:(id)_value toPropertyWithKey:(NSString *)_key 
352   ofObject:(id)_object
353 {
354   NSString *selname;
355   SEL      sel;
356   
357   selname = [[NSString alloc] initWithFormat:@"addTo%@:", 
358                               [_key capitalizedString]];
359   if ((sel = NSSelectorFromString(selname)) == NULL) {
360     if (doDebug) {
361       NSLog(@"got no selector for key '%@', selname '%@' !",
362             _key, selname);
363     }
364   }
365   [selname release]; selname = nil;
366   
367   if (doDebug) {
368     NSLog(@"%s: adding value %@ to %@ of %@", __PRETTY_FUNCTION__,
369           _value, _key, _object);
370     NSLog(@"  selector: %@", NSStringFromSelector(sel));
371   }
372   
373   if ((sel != NULL) && [_object respondsToSelector:sel]) {
374     [_object performSelector:sel withObject:_value];
375   }
376   else {
377     id v;
378     
379     v = [_object valueForKey:_key];
380     
381     if ([self isToManyKey:_key]) {
382       /* to-many relationship */
383
384       if (v == nil) {
385         [_object takeValue:[NSArray arrayWithObject:_value] forKey:_key];
386       }
387       else {
388         if ([v respondsToSelector:@selector(addObject:)])
389           /* the value is mutable */
390           [v addObject:_value];
391         else {
392           /* the value is immutable */
393           v = [v arrayByAddingObject:_value];
394           [_object takeValue:v forKey:_key];
395         }
396       }
397     }
398     else {
399       NSLog(@" APPLIED ON TO-ONE (%@) !", _key);
400       /* to-one relationship */
401       if (v != _value)
402         [_object takeValue:v forKey:_key];
403     }
404   }
405 }
406
407 @end /* SaxTagModel */