2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
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
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.
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
22 #include "SaxObjectModel.h"
25 static NSDictionary *mapDictsToObjects(NSDictionary *_dict, Class clazz) {
26 NSMutableDictionary *md;
30 md = [NSMutableDictionary dictionaryWithCapacity:16];
32 e = [_dict keyEnumerator];
33 while ((key = [e nextObject])) {
36 obj = [[clazz alloc] initWithDictionary:[_dict objectForKey:key]];
37 [md setObject:obj forKey:key];
43 @implementation SaxObjectModel
45 static BOOL doDebug = NO;
46 static NSArray *searchPathes = nil;
48 + (NSArray *)saxMappingSearchPathes {
49 if (searchPathes == nil) {
54 env = [[NSProcessInfo processInfo] environment];
55 ma = [NSMutableArray arrayWithCapacity:6];
57 #if COCOA_Foundation_LIBRARY
58 tmp = NSSearchPathForDirectoriesInDomains(NSAllLibrariesDirectory,
61 if ([tmp count] > 0) {
64 e = [tmp objectEnumerator];
65 while ((tmp = [e nextObject])) {
66 tmp = [tmp stringByAppendingPathComponent:@"SaxMappings"];
67 if (![ma containsObject:tmp])
72 if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil)
73 tmp = [env objectForKey:@"GNUSTEP_PATHLIST"];
74 tmp = [tmp componentsSeparatedByString:@":"];
75 if ([tmp count] > 0) {
78 e = [tmp objectEnumerator];
79 while ((tmp = [e nextObject])) {
80 tmp = [tmp stringByAppendingPathComponent:@"Library/SaxMappings"];
81 if (![ma containsObject:tmp])
88 [ma addObject:@"/usr/local/share/sope-4.3/saxmappings/"];
89 [ma addObject:@"/usr/share/sope-4.3/saxmappings/"];
90 searchPathes = [ma copy];
92 if ([searchPathes count] == 0)
93 NSLog(@"%s: no search pathes were found!", __PRETTY_FUNCTION__);
98 + (id)modelWithName:(NSString *)_name {
99 NSFileManager *fileManager;
100 NSEnumerator *pathes;
103 /* first look in main bundle */
105 if ((path = [[NSBundle mainBundle] pathForResource:_name ofType:@"xmap"]))
106 return [self modelWithContentsOfFile:path];
108 /* then in Library */
110 fileManager = [NSFileManager defaultManager];
111 pathes = [[[self class] saxMappingSearchPathes] objectEnumerator];
112 _name = [_name stringByAppendingPathExtension:@"xmap"];
114 while ((path = [pathes nextObject])) {
117 path = [path stringByAppendingPathComponent:_name];
119 if (![fileManager fileExistsAtPath:path isDirectory:&isDir])
127 return [self modelWithContentsOfFile:path];
130 + (id)modelWithContentsOfFile:(NSString *)_path {
133 if ((dict = [NSDictionary dictionaryWithContentsOfFile:_path]) == nil)
136 return [[[self alloc] initWithDictionary:dict] autorelease];
139 - (id)initWithDictionary:(NSDictionary *)_dict {
141 [mapDictsToObjects(_dict, [SaxNamespaceModel class]) retain];
146 [self->nsToModel release];
152 - (SaxTagModel *)modelForTag:(NSString *)_localName namespace:(NSString *)_ns {
153 SaxNamespaceModel *nsmap;
155 if ((nsmap = [self->nsToModel objectForKey:_ns]) == nil) {
156 if ((nsmap = [self->nsToModel objectForKey:@"*"]) == nil)
159 return [nsmap modelForTag:_localName];
162 /* faking dictionary */
164 - (id)objectForKey:(id)_key {
165 return [self->nsToModel objectForKey:_key];
168 @end /* SaxMappingModel */
170 @implementation SaxNamespaceModel
172 - (id)initWithDictionary:(NSDictionary *)_dict {
173 self->tagToModel = [mapDictsToObjects(_dict, [SaxTagModel class]) retain];
178 [self->tagToModel release];
184 - (SaxTagModel *)modelForTag:(NSString *)_localName {
187 if ((map = [self->tagToModel objectForKey:_localName]))
189 if ((map = [self->tagToModel objectForKey:@"*"]))
194 /* faking dictionary */
196 - (id)objectForKey:(id)_key {
197 return [self->tagToModel objectForKey:_key];
200 @end /* SaxNamespaceModel */
202 @implementation SaxTagModel
204 - (NSDictionary *)_extractAttributeMapping:(NSDictionary *)as {
205 NSMutableDictionary *md;
208 NSDictionary *result;
210 md = [[NSMutableDictionary alloc] initWithCapacity:16];
212 keys = [as keyEnumerator];
213 while ((k = [keys nextObject])) {
216 val = [as objectForKey:k];
218 if ([val isKindOfClass:[NSString class]])
219 [md setObject:val forKey:k];
220 else if ([val count] == 0)
221 [md setObject:k forKey:k];
223 [md setObject:[(NSDictionary *)val objectForKey:@"key"] forKey:k];
231 - (id)initWithDictionary:(NSDictionary *)_dict {
232 if ((self = [super init])) {
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];
244 if ((as = [_dict objectForKey:@"attributes"]))
245 self->attrToKey = [self _extractAttributeMapping:as];
247 if ((rels = [_dict objectForKey:@"ToManyRelationships"])) {
248 NSMutableDictionary *md;
252 self->toManyRelationshipKeys = [[rels allKeys] copy];
254 md = [[NSMutableDictionary alloc] initWithCapacity:16];
256 keys = [self->toManyRelationshipKeys objectEnumerator];
257 while ((k = [keys nextObject])) {
261 tags = [rels objectForKey:k];
262 if ([tags isKindOfClass:[NSString class]])
263 tags = [NSArray arrayWithObject:tags];
264 tags = [tags objectEnumerator];
266 while ((tag = [tags nextObject])) {
269 if ((t = [md objectForKey:tag])) {
270 NSLog(@"SaxObjectModel: cannot map tag '%@' to key '%@', "
271 @"it is already mapped to key '%@'.",
275 [md setObject:k forKey:tag];
279 self->tagToKey = [md copy];
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];
297 [self->attrToKey release];
303 - (NSString *)className {
304 return self->className;
309 - (NSString *)tagKey {
312 - (NSString *)namespaceKey {
313 return self->namespaceKey;
315 - (NSString *)parentKey {
316 return self->parentKey;
318 - (NSString *)contentKey {
319 return self->contentKey;
322 - (NSDictionary *)defaultValues {
323 return self->defaultValues;
326 - (BOOL)isToManyKey:(NSString *)_key {
327 return [self->toManyRelationshipKeys containsObject:_key];
329 - (NSArray *)toManyRelationshipKeys {
330 return self->toManyRelationshipKeys;
333 - (BOOL)isToManyTag:(NSString *)_tag {
334 return ([self->tagToKey objectForKey:_tag] != nil) ? YES : NO;
337 - (NSString *)propertyKeyForChildTag:(NSString *)_tag {
338 return [self->tagToKey objectForKey:_tag];
341 - (NSArray *)attributeKeys {
342 return [self->attrToKey allKeys];
344 - (NSString *)propertyKeyForAttribute:(NSString *)_attr {
345 return [self->attrToKey objectForKey:_attr];
348 /* object operations */
350 - (void)addValue:(id)_value toPropertyWithKey:(NSString *)_key
356 selname = [[NSString alloc] initWithFormat:@"addTo%@:",
357 [_key capitalizedString]];
358 if ((sel = NSSelectorFromString(selname)) == NULL) {
360 NSLog(@"got no selector for key '%@', selname '%@' !",
364 [selname release]; selname = nil;
367 NSLog(@"%s: adding value %@ to %@ of %@", __PRETTY_FUNCTION__,
368 _value, _key, _object);
369 NSLog(@" selector: %@", NSStringFromSelector(sel));
372 if ((sel != NULL) && [_object respondsToSelector:sel]) {
373 [_object performSelector:sel withObject:_value];
378 v = [_object valueForKey:_key];
380 if ([self isToManyKey:_key]) {
381 /* to-many relationship */
384 [_object takeValue:[NSArray arrayWithObject:_value] forKey:_key];
387 if ([v respondsToSelector:@selector(addObject:)])
388 /* the value is mutable */
389 [v addObject:_value];
391 /* the value is immutable */
392 v = [v arrayByAddingObject:_value];
393 [_object takeValue:v forKey:_key];
398 NSLog(@" APPLIED ON TO-ONE (%@) !", _key);
399 /* to-one relationship */
401 [_object takeValue:v forKey:_key];
406 @end /* SaxTagModel */