]> err.no Git - sope/blob - sope-core/EOControl/EOKeyValueQualifier.m
fixed gcc 4.1 warnings
[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   
50   if (_selector == NULL) {
51     NSLog(@"WARNING(%s): got no selector for kv qualifier (key=%@)", 
52           __PRETTY_FUNCTION__, _key);
53   }
54   
55   return self;
56 }
57
58 - (id)init {
59   return [self initWithKey:nil operatorSelector:NULL value:nil];
60 }
61
62 - (void)dealloc {
63   [self->key   release];
64   [self->value release];
65   [super dealloc];
66 }
67
68 /* accessors */
69
70 - (NSString *)key {
71   return self->key;
72 }
73 - (SEL)selector {
74   return self->operator;
75 }
76 - (id)value {
77   return self->value;
78 }
79
80 /* bindings */
81
82 - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings
83   requiresAllVariables:(BOOL)_reqAll
84 {
85   static Class VarClass = Nil;
86   NSString *newKey;
87   id       newValue;
88   BOOL     needNew;
89   
90   if (VarClass == Nil) VarClass = [EOQualifierVariable class];
91   needNew = NO;
92
93   if ([self->key class] == VarClass) {
94     newKey = [_bindings objectForKey:[(EOQualifierVariable *)self->key key]];
95     if (newKey == nil) {
96       if (_reqAll)
97         // throw exception
98         ;
99       else
100         newKey = self->key;
101     }
102     else
103       needNew = YES;
104   }
105   else
106     newKey = self->key;
107
108   if ([self->value class] == VarClass) {
109     newValue = [_bindings objectForKey:[self->value key]];
110     if (newValue == nil) {
111       if (_reqAll)
112         // throw exception
113         ;
114       else
115         newValue = self->value;
116     }
117     else
118       needNew = YES;
119   }
120   else
121     newValue = self->value;
122
123   if (!needNew)
124     return self;
125
126   return [[[[self class] alloc]
127                          initWithKey:newKey
128                          operatorSelector:self->operator
129                          value:newValue] autorelease];
130 }
131
132 - (NSArray *)bindingKeys {
133   static Class VarClass = Nil;
134   Class keyClass, vClass;
135   if (VarClass == Nil) VarClass = [EOQualifierVariable class];
136   
137   keyClass = [self->key   class];
138   vClass   = [self->value class];
139   
140   if ((keyClass == VarClass) && (vClass == VarClass)) {
141     id o[2];
142     o[0] = [(EOQualifierVariable *)self->key   key];
143     o[1] = [(EOQualifierVariable *)self->value key];
144     return [NSArray arrayWithObjects:o count:2];
145   }
146   
147   if (keyClass == VarClass)
148     return [NSArray arrayWithObject:[(EOQualifierVariable *)self->key key]];
149   if (vClass == VarClass)
150     return [NSArray arrayWithObject:[(EOQualifierVariable *)self->value key]];
151   
152   return [NSArray array];
153 }
154
155 /* keys */
156
157 - (void)addQualifierKeysToSet:(NSMutableSet *)_keys {
158   /* new in WO 4.5 */
159   [_keys addObject:self->key];
160 }
161
162 /* evaluation */
163
164 - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx {
165   id   lv, rv;
166   BOOL (*m)(id, SEL, id);
167   BOOL result;
168   
169   if (_ctx == nil)
170     _ctx = [NSMutableDictionary dictionaryWithCapacity:16];
171   
172   if ((lv = [(NSDictionary *)_ctx objectForKey:self->key]) == nil) {
173     lv = [_object valueForKeyPath:self->key];
174     if (lv == nil) lv = null;
175     [(NSMutableDictionary *)_ctx setObject:lv forKey:self->key];
176   }
177   
178   rv = self->value != nil ? self->value : (id)null;
179   
180   if (debugEval) {
181     NSLog(@"Eval: EOKeyValueQualifier:(%@ %@)\n"
182           @"  compare %@<%@>\n  with %@<%@>",
183           self->key, NSStringFromSelector(self->operator),
184           lv, NSStringFromClass([lv class]),
185           rv, NSStringFromClass([rv class]));
186   }
187   
188   if ((m = (void *)[lv methodForSelector:self->operator]) == NULL) {
189     /* no such operator method ! */
190     [lv doesNotRecognizeSelector:self->operator];
191     return NO;
192   }
193   
194   result = m(lv, self->operator, rv);
195   if (debugEval)
196     NSLog(@"  %@", result ? @"MATCHES" : @"DOES NOT MATCH");
197   return result;
198 }
199 - (BOOL)evaluateWithObject:(id)_object {
200   return [self evaluateWithObject:_object inEvalContext:nil];
201 }
202
203 /* NSCoding */
204
205 - (void)encodeWithCoder:(NSCoder *)_coder {
206   [_coder encodeObject:self->key];
207   [_coder encodeObject:self->value];
208   [_coder encodeValueOfObjCType:@encode(SEL) at:&(self->operator)];
209 }
210 - (id)initWithCoder:(NSCoder *)_coder {
211   self->key   = [[_coder decodeObject] copyWithZone:[self zone]];
212   self->value = [[_coder decodeObject] retain];
213   [_coder decodeValueOfObjCType:@encode(SEL) at:&(self->operator)];
214
215   if (self->operator == NULL) {
216     NSLog(@"WARNING(%s): decoded no selector for kv qualifier (key=%@)", 
217           __PRETTY_FUNCTION__, self->key);
218   }
219   
220   return self;
221 }
222
223 /* Comparing */
224
225 - (BOOL)isEqualToQualifier:(EOQualifier *)_qual {
226   if (![self->key isEqual:[(EOKeyValueQualifier *)_qual key]])
227     return NO;
228   if (![self->value isEqual:[(EOKeyValueQualifier *)_qual value]])
229     return NO;
230   if (sel_eq(self->operator, [(EOKeyValueQualifier *)_qual selector]))
231     return YES;
232   return NO;
233 }
234
235 /* remapping keys */
236
237 - (EOQualifier *)qualifierByApplyingTransformer:(id)_transformer
238   inContext:(id)_ctx
239 {
240   if ([_transformer respondsToSelector:
241                       @selector(transformKeyValueQualifier:inContext:)]) {
242     if (debugTransform)
243       NSLog(@"transformer: %@\n  transform: %@", _transformer, self);
244     return [_transformer transformKeyValueQualifier:self inContext:_ctx];
245   }
246   else {
247     if (debugTransform)
248       NSLog(@"EOKeyValueQualifier: not transforming using %@", _transformer);
249     return [[self retain] autorelease];
250   }
251 }
252
253 - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map {
254   EOKeyValueQualifier *kvq;
255   NSString *k;
256   
257   k = [_map objectForKey:self->key];
258   if (k == nil) k = self->key;
259   
260   kvq = [[EOKeyValueQualifier alloc] 
261           initWithKey:k operatorSelector:self->operator value:self->value];
262   return [kvq autorelease];
263 }
264
265 /* key/value archiving */
266
267 - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver {
268   if ((self = [super initWithKeyValueUnarchiver:_unarchiver]) != nil) {
269     NSString *s;
270     
271     self->key   = [[_unarchiver decodeObjectForKey:@"key"]   copy];
272     self->value = [[_unarchiver decodeObjectForKey:@"value"] retain];
273     
274     if ((s = [_unarchiver decodeObjectForKey:@"selectorName"]) != nil) {
275       if (![s hasSuffix:@":"]) s = [s stringByAppendingString:@":"];
276       self->operator = NSSelectorFromString(s);
277     }
278     else if ((s = [_unarchiver decodeObjectForKey:@"selector"]) != nil)
279       self->operator = NSSelectorFromString(s);
280     else {
281       NSLog(@"WARNING(%s): decoded no selector/selectorName for kv qualifier "
282             @"(key=%@)", 
283             __PRETTY_FUNCTION__, self->key);
284       self->operator = EOQualifierOperatorEqual;
285     }
286     
287     if (self->operator == NULL) {
288       NSLog(@"WARNING(%s): decoded no selector for kv qualifier (key=%@)", 
289             __PRETTY_FUNCTION__, self->key);
290       self->operator = EOQualifierOperatorEqual;
291     }
292   }
293   return self;
294 }
295 - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
296   NSString *s;
297   
298   [super encodeWithKeyValueArchiver:_archiver];
299   
300   [_archiver encodeObject:[self key]   forKey:@"key"];
301   [_archiver encodeObject:[self value] forKey:@"value"];
302   
303   s = NSStringFromSelector([self selector]);
304   if ([s hasSuffix:@":"]) s = [s substringToIndex:[s length] - 1];
305   [_archiver encodeObject:s forKey:@"selectorName"];
306 }
307
308 /* description */
309
310 - (NSString *)description {
311   NSMutableString *s;
312   NSString *tmp;
313   
314   s = [NSMutableString stringWithCapacity:64];
315   
316   if (self->key != nil)
317     [s appendString:self->key];
318   else
319     [s appendString:@"[NO KEY]"];
320   
321   [s appendString:@" "];
322   
323   if ((tmp = [EOQualifier stringForOperatorSelector:self->operator]) != nil)
324     [s appendString:tmp];
325   else if (self->operator != NULL)
326     [s appendString:@"[NO STR OPERATOR]"];
327   else
328     [s appendString:@"[NO OPERATOR]"];
329     
330   [s appendString:@" "];
331   
332   if ((tmp = [self->value qualifierDescription]) != nil)
333     [s appendString:tmp];
334   else
335     [s appendString:@"nil"];
336   return s;
337 }
338
339 @end /* EOKeyValueQualifier */