2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
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
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.
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
22 #include <EOControl/EOQualifier.h>
23 #include <EOControl/EONull.h>
26 @interface NSObject(QualifierDescription)
27 - (NSString *)qualifierDescription;
30 @implementation EOKeyValueQualifier
32 static BOOL debugEval = NO;
33 static BOOL debugTransform = NO;
34 static EONull *null = nil;
38 null = [[EONull null] retain];
39 debugEval = [EOQualifier isEvaluationDebuggingEnabled];
42 - (id)initWithKey:(NSString *)_key
43 operatorSelector:(SEL)_selector
46 self->key = [_key copyWithZone:NULL];
47 self->value = [_value retain];
48 self->operator = _selector;
50 if (_selector == NULL) {
51 NSLog(@"WARNING(%s): got no selector for kv qualifier (key=%@)",
52 __PRETTY_FUNCTION__, _key);
59 return [self initWithKey:nil operatorSelector:NULL value:nil];
64 [self->value release];
74 return self->operator;
82 - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings
83 requiresAllVariables:(BOOL)_reqAll
85 static Class VarClass = Nil;
90 if (VarClass == Nil) VarClass = [EOQualifierVariable class];
93 if ([self->key class] == VarClass) {
94 newKey = [_bindings objectForKey:[(EOQualifierVariable *)self->key key]];
108 if ([self->value class] == VarClass) {
109 newValue = [_bindings objectForKey:[self->value key]];
110 if (newValue == nil) {
115 newValue = self->value;
121 newValue = self->value;
126 return [[[[self class] alloc]
128 operatorSelector:self->operator
129 value:newValue] autorelease];
132 - (NSArray *)bindingKeys {
133 static Class VarClass = Nil;
134 Class keyClass, vClass;
135 if (VarClass == Nil) VarClass = [EOQualifierVariable class];
137 keyClass = [self->key class];
138 vClass = [self->value class];
140 if ((keyClass == VarClass) && (vClass == VarClass)) {
142 o[0] = [(EOQualifierVariable *)self->key key];
143 o[1] = [(EOQualifierVariable *)self->value key];
144 return [NSArray arrayWithObjects:o count:2];
147 if (keyClass == VarClass)
148 return [NSArray arrayWithObject:[(EOQualifierVariable *)self->key key]];
149 if (vClass == VarClass)
150 return [NSArray arrayWithObject:[(EOQualifierVariable *)self->value key]];
152 return [NSArray array];
157 - (void)addQualifierKeysToSet:(NSMutableSet *)_keys {
159 [_keys addObject:self->key];
164 - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx {
166 BOOL (*m)(id, SEL, id);
170 _ctx = [NSMutableDictionary dictionaryWithCapacity:16];
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];
178 rv = self->value != nil ? self->value : (id)null;
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]));
188 if ((m = (void *)[lv methodForSelector:self->operator]) == NULL) {
189 /* no such operator method ! */
190 [lv doesNotRecognizeSelector:self->operator];
194 result = m(lv, self->operator, rv);
196 NSLog(@" %@", result ? @"MATCHES" : @"DOES NOT MATCH");
199 - (BOOL)evaluateWithObject:(id)_object {
200 return [self evaluateWithObject:_object inEvalContext:nil];
205 - (void)encodeWithCoder:(NSCoder *)_coder {
206 [_coder encodeObject:self->key];
207 [_coder encodeObject:self->value];
208 [_coder encodeValueOfObjCType:@encode(SEL) at:&(self->operator)];
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)];
215 if (self->operator == NULL) {
216 NSLog(@"WARNING(%s): decoded no selector for kv qualifier (key=%@)",
217 __PRETTY_FUNCTION__, self->key);
225 - (BOOL)isEqualToQualifier:(EOQualifier *)_qual {
226 if (![self->key isEqual:[(EOKeyValueQualifier *)_qual key]])
228 if (![self->value isEqual:[(EOKeyValueQualifier *)_qual value]])
230 if (sel_eq(self->operator, [(EOKeyValueQualifier *)_qual selector]))
237 - (EOQualifier *)qualifierByApplyingTransformer:(id)_transformer
240 if ([_transformer respondsToSelector:
241 @selector(transformKeyValueQualifier:inContext:)]) {
243 NSLog(@"transformer: %@\n transform: %@", _transformer, self);
244 return [_transformer transformKeyValueQualifier:self inContext:_ctx];
248 NSLog(@"EOKeyValueQualifier: not transforming using %@", _transformer);
249 return [[self retain] autorelease];
253 - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map {
254 EOKeyValueQualifier *kvq;
257 k = [_map objectForKey:self->key];
258 if (k == nil) k = self->key;
260 kvq = [[EOKeyValueQualifier alloc]
261 initWithKey:k operatorSelector:self->operator value:self->value];
262 return [kvq autorelease];
265 /* key/value archiving */
267 - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver {
268 if ((self = [super initWithKeyValueUnarchiver:_unarchiver]) != nil) {
271 self->key = [[_unarchiver decodeObjectForKey:@"key"] copy];
272 self->value = [[_unarchiver decodeObjectForKey:@"value"] retain];
274 if ((s = [_unarchiver decodeObjectForKey:@"selectorName"]) != nil) {
275 if (![s hasSuffix:@":"]) s = [s stringByAppendingString:@":"];
276 self->operator = NSSelectorFromString(s);
278 else if ((s = [_unarchiver decodeObjectForKey:@"selector"]) != nil)
279 self->operator = NSSelectorFromString(s);
281 NSLog(@"WARNING(%s): decoded no selector/selectorName for kv qualifier "
283 __PRETTY_FUNCTION__, self->key);
284 self->operator = EOQualifierOperatorEqual;
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;
295 - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
298 [super encodeWithKeyValueArchiver:_archiver];
300 [_archiver encodeObject:[self key] forKey:@"key"];
301 [_archiver encodeObject:[self value] forKey:@"value"];
303 s = NSStringFromSelector([self selector]);
304 if ([s hasSuffix:@":"]) s = [s substringToIndex:[s length] - 1];
305 [_archiver encodeObject:s forKey:@"selectorName"];
310 - (NSString *)description {
314 s = [NSMutableString stringWithCapacity:64];
316 if (self->key != nil)
317 [s appendString:self->key];
319 [s appendString:@"[NO KEY]"];
321 [s appendString:@" "];
323 if ((tmp = [EOQualifier stringForOperatorSelector:self->operator]) != nil)
324 [s appendString:tmp];
325 else if (self->operator != NULL)
326 [s appendString:@"[NO STR OPERATOR]"];
328 [s appendString:@"[NO OPERATOR]"];
330 [s appendString:@" "];
332 if ((tmp = [self->value qualifierDescription]) != nil)
333 [s appendString:tmp];
335 [s appendString:@"nil"];
339 @end /* EOKeyValueQualifier */