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