]> err.no Git - sope/blob - sope-core/EOControl/EOKeyValueQualifier.m
added EOKeyValueArchiving to fetch-spec and qualifier classes
[sope] / sope-core / EOControl / EOKeyValueQualifier.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE 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   SOPE 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 SOPE; 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 <EOControl/EOQualifier.h>
23 #include <EOControl/EONull.h>
24 #include "common.h"
25
26 @interface NSObject(QualifierDescription)
27 - (NSString *)qualifierDescription;
28 @end
29
30 @implementation EOKeyValueQualifier
31
32 static BOOL   debugEval      = NO;
33 static BOOL   debugTransform = NO;
34 static EONull *null = nil;
35
36 + (void)initialize {
37   if (null == nil)
38     null = [[EONull null] retain];
39   debugEval = [EOQualifier isEvaluationDebuggingEnabled];
40 }
41
42 - (id)initWithKey:(NSString *)_key
43   operatorSelector:(SEL)_selector
44   value:(id)_value
45 {
46   self->key      = [_key   copyWithZone:NULL];
47   self->value    = [_value retain];
48   self->operator = _selector;
49   return self;
50 }
51
52 - (void)dealloc {
53   [self->key   release];
54   [self->value release];
55   [super dealloc];
56 }
57
58 /* accessors */
59
60 - (NSString *)key {
61   return self->key;
62 }
63 - (SEL)selector {
64   return self->operator;
65 }
66 - (id)value {
67   return self->value;
68 }
69
70 /* bindings */
71
72 - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings
73   requiresAllVariables:(BOOL)_reqAll
74 {
75   static Class VarClass = Nil;
76   NSString *newKey;
77   id       newValue;
78   BOOL     needNew;
79   
80   if (VarClass == Nil) VarClass = [EOQualifierVariable class];
81   needNew = NO;
82
83   if ([self->key class] == VarClass) {
84     newKey = [_bindings objectForKey:[(EOQualifierVariable *)self->key key]];
85     if (newKey == nil) {
86       if (_reqAll)
87         // throw exception
88         ;
89       else
90         newKey = self->key;
91     }
92     else
93       needNew = YES;
94   }
95   else
96     newKey = self->key;
97
98   if ([self->value class] == VarClass) {
99     newValue = [_bindings objectForKey:[self->value key]];
100     if (newValue == nil) {
101       if (_reqAll)
102         // throw exception
103         ;
104       else
105         newValue = self->value;
106     }
107     else
108       needNew = YES;
109   }
110   else
111     newValue = self->value;
112
113   if (!needNew)
114     return self;
115
116   return [[[[self class] alloc]
117                          initWithKey:newKey
118                          operatorSelector:self->operator
119                          value:newValue] autorelease];
120 }
121
122 - (NSArray *)bindingKeys {
123   static Class VarClass = Nil;
124   Class keyClass, vClass;
125   if (VarClass == Nil) VarClass = [EOQualifierVariable class];
126   
127   keyClass = [self->key   class];
128   vClass   = [self->value class];
129   
130   if ((keyClass == VarClass) && (vClass == VarClass)) {
131     id o[2];
132     o[0] = [(EOQualifierVariable *)self->key   key];
133     o[1] = [(EOQualifierVariable *)self->value key];
134     return [NSArray arrayWithObjects:o count:2];
135   }
136   
137   if (keyClass == VarClass)
138     return [NSArray arrayWithObject:[(EOQualifierVariable *)self->key key]];
139   if (vClass == VarClass)
140     return [NSArray arrayWithObject:[(EOQualifierVariable *)self->value key]];
141   
142   return [NSArray array];
143 }
144
145 /* keys */
146
147 - (void)addQualifierKeysToSet:(NSMutableSet *)_keys {
148   /* new in WO 4.5 */
149   [_keys addObject:self->key];
150 }
151
152 /* evaluation */
153
154 - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx {
155   id   lv, rv;
156   BOOL (*m)(id, SEL, id);
157   BOOL result;
158   
159   if (_ctx == nil)
160     _ctx = [NSMutableDictionary dictionaryWithCapacity:16];
161   
162   if ((lv = [(NSDictionary *)_ctx objectForKey:self->key]) == nil) {
163     lv = [_object valueForKeyPath:self->key];
164     if (lv == nil) lv = null;
165     [(NSMutableDictionary *)_ctx setObject:lv forKey:self->key];
166   }
167   
168   rv = self->value ? self->value : null;
169   
170   if (debugEval) {
171     NSLog(@"Eval: EOKeyValueQualifier:(%@ %@)\n"
172           @"  compare %@<%@>\n  with %@<%@>",
173           self->key, NSStringFromSelector(self->operator),
174           lv, NSStringFromClass([lv class]),
175           rv, NSStringFromClass([rv class]));
176   }
177   
178   if ((m = (void *)[lv methodForSelector:self->operator]) == NULL) {
179     /* no such operator method ! */
180     [lv doesNotRecognizeSelector:self->operator];
181     return NO;
182   }
183   
184   result = m(lv, self->operator, rv);
185   if (debugEval)
186     NSLog(@"  %@", result ? @"MATCHES" : @"DOES NOT MATCH");
187   return result;
188 }
189 - (BOOL)evaluateWithObject:(id)_object {
190   return [self evaluateWithObject:_object inEvalContext:nil];
191 }
192
193 /* NSCoding */
194
195 - (void)encodeWithCoder:(NSCoder *)_coder {
196   [_coder encodeObject:self->key];
197   [_coder encodeObject:self->value];
198   [_coder encodeValueOfObjCType:@encode(SEL) at:&(self->operator)];
199 }
200 - (id)initWithCoder:(NSCoder *)_coder {
201   self->key   = [[_coder decodeObject] copyWithZone:[self zone]];
202   self->value = [[_coder decodeObject] retain];
203   [_coder decodeValueOfObjCType:@encode(SEL) at:&(self->operator)];
204   return self;
205 }
206
207 /* Comparing */
208
209 - (BOOL)isEqualToQualifier:(EOQualifier *)_qual {
210   if (![self->key isEqual:[(EOKeyValueQualifier *)_qual key]])
211     return NO;
212   if (![self->value isEqual:[(EOKeyValueQualifier *)_qual value]])
213     return NO;
214   if (sel_eq(self->operator, [(EOKeyValueQualifier *)_qual selector]))
215     return YES;
216   return NO;
217 }
218
219 /* remapping keys */
220
221 - (EOQualifier *)qualifierByApplyingTransformer:(id)_transformer
222   inContext:(id)_ctx
223 {
224   if ([_transformer respondsToSelector:
225                       @selector(transformKeyValueQualifier:inContext:)]) {
226     if (debugTransform)
227       NSLog(@"transformer: %@\n  transform: %@", _transformer, self);
228     return [_transformer transformKeyValueQualifier:self inContext:_ctx];
229   }
230   else {
231     if (debugTransform)
232       NSLog(@"EOKeyValueQualifier: not transforming using %@", _transformer);
233     return [[self retain] autorelease];
234   }
235 }
236
237 - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map {
238   EOKeyValueQualifier *kvq;
239   NSString *k;
240   
241   k = [_map objectForKey:self->key];
242   if (k == nil) k = self->key;
243   
244   kvq = [[EOKeyValueQualifier alloc] 
245           initWithKey:k operatorSelector:self->operator value:self->value];
246   return [kvq autorelease];
247 }
248
249 /* key/value archiving */
250
251 - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver {
252   if ((self = [super initWithKeyValueUnarchiver:_unarchiver]) != nil) {
253     NSString *s;
254     
255     self->key   = [[_unarchiver decodeObjectForKey:@"key"]   copy];
256     self->value = [[_unarchiver decodeObjectForKey:@"value"] retain];
257     
258     if ((s = [_unarchiver decodeObjectForKey:@"selectorName"]) != nil) {
259       if (![s hasSuffix:@":"]) s = [s stringByAppendingString:@":"];
260       self->operator = NSSelectorFromString(s);
261     }
262     else if ((s = [_unarchiver decodeObjectForKey:@"selector"]) != nil)
263       self->operator = NSSelectorFromString(s);
264   }
265   return self;
266 }
267 - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
268   NSString *s;
269   
270   [super encodeWithKeyValueArchiver:_archiver];
271   
272   [_archiver encodeObject:[self key]   forKey:@"key"];
273   [_archiver encodeObject:[self value] forKey:@"value"];
274   
275   s = NSStringFromSelector([self selector]);
276   if ([s hasSuffix:@":"]) s = [s substringToIndex:[s length] - 1];
277   [_archiver encodeObject:s forKey:@"selectorName"];
278 }
279
280 /* description */
281
282 - (NSString *)description {
283   NSMutableString *s;
284   
285   s = [NSMutableString stringWithCapacity:64];
286   [s appendString:self->key];
287   [s appendString:@" "];
288   [s appendString:[EOQualifier stringForOperatorSelector:self->operator]];
289   [s appendString:@" "];
290   [s appendString:[self->value qualifierDescription]];
291   return s;
292 }
293
294 @end /* EOKeyValueQualifier */