]> err.no Git - sope/blob - sope-core/EOControl/EOKeyValueArchiver.m
removed NGJavaScript support
[sope] / sope-core / EOControl / EOKeyValueArchiver.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
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 "EOKeyValueArchiver.h"
24 #include "common.h"
25
26 @implementation EOKeyValueArchiver
27
28 - (id)init {
29   if ((self = [super init])) {
30     self->plist = [[NSMutableDictionary alloc] init];
31   }
32   return self;
33 }
34
35 - (void)dealloc {
36   [self->plist release];
37   [super dealloc];
38 }
39
40 /* coding */
41
42 static BOOL isPListObject(id _obj) {
43   if ([_obj isKindOfClass:[NSString class]])
44     return YES;
45   if ([_obj isKindOfClass:[NSData class]])
46     return YES;
47   if ([_obj isKindOfClass:[NSArray class]])
48     return YES;
49   return NO;
50 }
51
52 - (void)encodeObject:(id)_obj forKey:(NSString *)_key {
53   NSMutableDictionary *oldPlist;
54
55   if (isPListObject(_obj)) {
56     id c;
57     c = [_obj copy];
58     [self->plist setObject:c forKey:_key];
59     [c release];
60     return;
61   }
62   
63   oldPlist = self->plist;
64   self->plist = [[NSMutableDictionary alloc] init];
65   
66   if (_obj) {
67     /* store class name */
68     [self->plist setObject:NSStringFromClass([_obj class]) forKey:@"class"];
69
70     /* let object store itself */
71     [_obj encodeWithKeyValueArchiver:self];
72   }
73   else {
74     /* nil ??? */
75   }
76
77   [oldPlist setObject:self->plist forKey:_key];
78   [self->plist release];
79   self->plist = oldPlist;
80 }
81
82 - (void)encodeReferenceToObject:(id)_obj forKey:(NSString *)_key {
83   if ([self->delegate respondsToSelector:
84            @selector(archiver:referenceToEncodeForObject:)])
85     _obj = [self->delegate archiver:self referenceToEncodeForObject:_obj];
86
87   /* if _obj wasn't replaced by the delegate, encode the object in place .. */
88   [self encodeObject:_obj forKey:_key];
89 }
90
91 - (void)encodeBool:(BOOL)_flag forKey:(NSString *)_key {
92   /* NO values are not archived .. */
93   if (_flag) {
94     [self->plist setObject:@"YES" forKey:_key];
95   }
96 }
97 - (void)encodeInt:(int)_value forKey:(NSString *)_key {
98   [self->plist setObject:[NSString stringWithFormat:@"%i", _value] forKey:_key];
99 }
100
101 - (NSDictionary *)dictionary {
102   return [[self->plist copy] autorelease];
103 }
104
105 /* delegate */
106
107 - (void)setDelegate:(id)_delegate {
108   self->delegate = _delegate;
109 }
110 - (id)delegate {
111   return self->delegate;
112 }
113
114 @end /* EOKeyValueArchiver */
115
116 @implementation EOKeyValueUnarchiver
117
118 - (id)initWithDictionary:(NSDictionary *)_dict {
119   self->plist = [_dict copy];
120   self->unarchivedObjects = [[NSMutableArray alloc] init];
121   self->awakeObjects      = [[NSMutableSet alloc] init]; // should be a hashtable
122   return self;
123 }
124 - (id)init {
125   [self release];
126   return nil;
127 }
128
129 - (void)dealloc {
130   [self->awakeObjects      release];
131   [self->unarchivedObjects release];
132   [self->plist             release];
133   [super dealloc];
134 }
135
136 /* decoding */
137
138 - (id)decodeObjectForKey:(NSString *)_key {
139   NSString     *className;
140   NSDictionary *lastParent;
141   id obj;
142
143   lastParent   = self->parent;
144   self->parent = self->plist;
145   self->plist  = [(NSDictionary *)self->parent objectForKey:_key];
146
147   if (![self->plist isKindOfClass:[NSDictionary class]]) {
148     obj = [[self->plist copy] autorelease];
149   }
150   else if ((className = [self->plist objectForKey:@"class"]) != nil) {
151     obj = [NSClassFromString(className) alloc];
152     obj = [obj initWithKeyValueUnarchiver:self];
153     
154     [self->unarchivedObjects addObject:obj];
155     [obj release];
156   }
157   else {
158     obj = nil;
159   }
160   
161   self->plist  = self->parent;
162   self->parent = lastParent;
163   
164   return obj;
165 }
166 - (id)decodeObjectReferenceForKey:(NSString *)_key {
167   id refObj, obj;
168
169   refObj = [self decodeObjectForKey:_key];
170
171   if ([self->delegate respondsToSelector:
172            @selector(unarchiver:objectForReference:)]) {
173     obj = [self->delegate unarchiver:self objectForReference:refObj];
174     
175     [self->unarchivedObjects addObject:obj];
176   }
177   else {
178     /* if delegate does not dereference, pass back the reference object */
179     obj = refObj;
180   }
181   return obj;
182 }
183
184 - (BOOL)decodeBoolForKey:(NSString *)_key {
185   return [[self->plist objectForKey:_key] boolValue];
186 }
187 - (int)decodeIntForKey:(NSString *)_key {
188   return [[self->plist objectForKey:_key] intValue];
189 }
190
191 /* operations */
192
193 - (void)ensureObjectAwake:(id)_object {
194   if (![self->awakeObjects containsObject:_object]) {
195     if ([_object respondsToSelector:@selector(awakeFromKeyValueUnarchiver:)]) {
196       [_object awakeFromKeyValueUnarchiver:self];
197     }
198     [self->awakeObjects addObject:_object];
199   }
200 }
201 - (void)awakeObjects {
202   NSEnumerator *e;
203   id obj;
204
205   e = [self->unarchivedObjects objectEnumerator];
206   while ((obj = [e nextObject]))
207     [self ensureObjectAwake:obj];
208 }
209
210 - (void)finishInitializationOfObjects {
211   NSEnumerator *e;
212   id obj;
213
214   e = [self->unarchivedObjects objectEnumerator];
215   while ((obj = [e nextObject])) {
216     if ([obj respondsToSelector:
217                @selector(finishInitializationWithKeyValueUnarchiver:)])
218       [obj finishInitializationWithKeyValueUnarchiver:self];
219   }
220 }
221
222 - (id)parent {
223   return self->parent;
224 }
225
226 /* delegate */
227
228 - (void)setDelegate:(id)_delegate {
229   self->delegate = _delegate;
230 }
231 - (id)delegate {
232   return self->delegate;
233 }
234
235 @end /* EOKeyValueUnarchiver */