/* Copyright (C) 2000-2004 SKYRIX Software AG This file is part of OpenGroupware.org. OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "EOKeyValueArchiver.h" #include "common.h" @implementation EOKeyValueArchiver - (id)init { if ((self = [super init])) { self->plist = [[NSMutableDictionary alloc] init]; } return self; } - (void)dealloc { [self->plist release]; [super dealloc]; } /* coding */ static BOOL isPListObject(id _obj) { if ([_obj isKindOfClass:[NSString class]]) return YES; if ([_obj isKindOfClass:[NSData class]]) return YES; if ([_obj isKindOfClass:[NSArray class]]) return YES; return NO; } - (void)encodeObject:(id)_obj forKey:(NSString *)_key { NSMutableDictionary *oldPlist; if (isPListObject(_obj)) { id c; c = [_obj copy]; [self->plist setObject:c forKey:_key]; [c release]; return; } oldPlist = self->plist; self->plist = [[NSMutableDictionary alloc] init]; if (_obj) { /* store class name */ [self->plist setObject:NSStringFromClass([_obj class]) forKey:@"class"]; /* let object store itself */ [_obj encodeWithKeyValueArchiver:self]; } else { /* nil ??? */ } [oldPlist setObject:self->plist forKey:_key]; [self->plist release]; self->plist = oldPlist; } - (void)encodeReferenceToObject:(id)_obj forKey:(NSString *)_key { if ([self->delegate respondsToSelector: @selector(archiver:referenceToEncodeForObject:)]) _obj = [self->delegate archiver:self referenceToEncodeForObject:_obj]; /* if _obj wasn't replaced by the delegate, encode the object in place .. */ [self encodeObject:_obj forKey:_key]; } - (void)encodeBool:(BOOL)_flag forKey:(NSString *)_key { /* NO values are not archived .. */ if (_flag) { [self->plist setObject:@"YES" forKey:_key]; } } - (void)encodeInt:(int)_value forKey:(NSString *)_key { [self->plist setObject:[NSString stringWithFormat:@"%i", _value] forKey:_key]; } - (NSDictionary *)dictionary { return [[self->plist copy] autorelease]; } /* delegate */ - (void)setDelegate:(id)_delegate { self->delegate = _delegate; } - (id)delegate { return self->delegate; } @end /* EOKeyValueArchiver */ @implementation EOKeyValueUnarchiver - (id)initWithDictionary:(NSDictionary *)_dict { self->plist = [_dict copy]; self->unarchivedObjects = [[NSMutableArray alloc] init]; self->awakeObjects = [[NSMutableSet alloc] init]; // should be a hashtable return self; } - (id)init { [self release]; return nil; } - (void)dealloc { [self->awakeObjects release]; [self->unarchivedObjects release]; [self->plist release]; [super dealloc]; } /* decoding */ - (id)decodeObjectForKey:(NSString *)_key { NSString *className; NSDictionary *lastParent; id obj; lastParent = self->parent; self->parent = self->plist; self->plist = [(NSDictionary *)self->parent objectForKey:_key]; if (![self->plist isKindOfClass:[NSDictionary class]]) { obj = [[self->plist copy] autorelease]; } else if ((className = [self->plist objectForKey:@"class"]) != nil) { obj = [NSClassFromString(className) alloc]; obj = [obj initWithKeyValueUnarchiver:self]; [self->unarchivedObjects addObject:obj]; [obj release]; } else { obj = nil; } self->plist = self->parent; self->parent = lastParent; return obj; } - (id)decodeObjectReferenceForKey:(NSString *)_key { id refObj, obj; refObj = [self decodeObjectForKey:_key]; if ([self->delegate respondsToSelector: @selector(unarchiver:objectForReference:)]) { obj = [self->delegate unarchiver:self objectForReference:refObj]; [self->unarchivedObjects addObject:obj]; } else { /* if delegate does not dereference, pass back the reference object */ obj = refObj; } return obj; } - (BOOL)decodeBoolForKey:(NSString *)_key { return [[self->plist objectForKey:_key] boolValue]; } - (int)decodeIntForKey:(NSString *)_key { return [[self->plist objectForKey:_key] intValue]; } /* operations */ - (void)ensureObjectAwake:(id)_object { if (![self->awakeObjects containsObject:_object]) { if ([_object respondsToSelector:@selector(awakeFromKeyValueUnarchiver:)]) { [_object awakeFromKeyValueUnarchiver:self]; } [self->awakeObjects addObject:_object]; } } - (void)awakeObjects { NSEnumerator *e; id obj; e = [self->unarchivedObjects objectEnumerator]; while ((obj = [e nextObject])) [self ensureObjectAwake:obj]; } - (void)finishInitializationOfObjects { NSEnumerator *e; id obj; e = [self->unarchivedObjects objectEnumerator]; while ((obj = [e nextObject])) { if ([obj respondsToSelector: @selector(finishInitializationWithKeyValueUnarchiver:)]) [obj finishInitializationWithKeyValueUnarchiver:self]; } } - (id)parent { return self->parent; } /* delegate */ - (void)setDelegate:(id)_delegate { self->delegate = _delegate; } - (id)delegate { return self->delegate; } @end /* EOKeyValueUnarchiver */