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@implementation EOKeyComparisonQualifier 27 28static EONull *null = nil; 29 30+ (void)initialize { 31 if (null == nil) 32 null = [[EONull null] retain]; 33} 34 35- (id)initWithLeftKey:(NSString *)_leftKey 36 operatorSelector:(SEL)_selector 37 rightKey:(NSString *)_rightKey; 38{ 39 self->leftKey = [_leftKey copyWithZone:NULL]; 40 self->rightKey = [_rightKey copyWithZone:NULL]; 41 self->operator = _selector; 42 return self; 43} 44 45- (void)dealloc { 46 [self->leftKey release]; 47 [self->rightKey release]; 48 [super dealloc]; 49} 50 51/* accessors */ 52 53- (NSString *)leftKey { 54 return self->leftKey; 55} 56- (NSString *)rightKey { 57 return self->rightKey; 58} 59- (SEL)selector { 60 return self->operator; 61} 62 63/* bindings */ 64 65- (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings 66 requiresAllVariables:(BOOL)_reqAll 67{ 68 static Class VarClass = Nil; 69 NSString *newLeftKey; 70 id newRightKey; 71 BOOL needNew; 72 73 if (VarClass == Nil) VarClass = [EOQualifierVariable class]; 74 needNew = NO; 75 76 if ([self->leftKey class] == VarClass) { 77 newLeftKey = 78 [_bindings objectForKey:[(EOQualifierVariable *)self->leftKey key]]; 79 if (newLeftKey == nil) { 80 if (_reqAll) 81 // throw exception 82 ; 83 else 84 newLeftKey = self->leftKey; 85 } 86 else 87 needNew = YES; 88 } 89 else 90 newLeftKey = self->leftKey; 91 92 if ([self->rightKey class] == VarClass) { 93 newRightKey = 94 [_bindings objectForKey:[(EOQualifierVariable *)self->rightKey key]]; 95 if (newRightKey == nil) { 96 if (_reqAll) 97 // throw exception 98 ; 99 else 100 newRightKey = self->rightKey; 101 } 102 else 103 needNew = YES; 104 } 105 else 106 newRightKey = self->rightKey; 107 108 if (!needNew) 109 return self; 110 111 return [[[[self class] alloc] 112 initWithLeftKey:newLeftKey 113 operatorSelector:self->operator 114 rightKey:newRightKey] 115 autorelease]; 116} 117 118- (NSArray *)bindingKeys { 119 static Class VarClass = Nil; 120 Class lkClass, rkClass; 121 if (VarClass == Nil) VarClass = [EOQualifierVariable class]; 122 123 lkClass = [self->leftKey class]; 124 rkClass = [self->rightKey class]; 125 126 if ((lkClass == VarClass) && (rkClass == VarClass)) { 127 id o[2]; 128 o[0] = [(EOQualifierVariable *)self->leftKey key]; 129 o[1] = [(EOQualifierVariable *)self->rightKey key]; 130 return [NSArray arrayWithObjects:o count:2]; 131 } 132 133 if (lkClass == VarClass) 134 return [NSArray arrayWithObject:[(EOQualifierVariable *)self->leftKey key]]; 135 if (rkClass == VarClass) { 136 return [NSArray arrayWithObject: 137 [(EOQualifierVariable *)self->rightKey key]]; 138 } 139 return [NSArray array]; 140} 141 142/* keys */ 143 144- (void)addQualifierKeysToSet:(NSMutableSet *)_keys { 145 /* new in WO 4.5 */ 146 [_keys addObject:self->leftKey]; 147 [_keys addObject:self->rightKey]; 148} 149 150/* evaluation */ 151 152- (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx { 153 id lv, rv; 154 BOOL (*m)(id, SEL, id); 155 156 if (_ctx == nil) 157 _ctx = [NSMutableDictionary dictionaryWithCapacity:16]; 158 159 if ((lv = [(NSDictionary *)_ctx objectForKey:self->leftKey]) == nil) { 160 lv = [_object valueForKeyPath:self->leftKey]; 161 if (lv == nil) lv = null; 162 [(NSMutableDictionary *)_ctx setObject:lv forKey:self->leftKey]; 163 } 164 if ((rv = [(NSDictionary *)_ctx objectForKey:self->rightKey]) == nil) { 165 rv = [_object valueForKeyPath:self->rightKey]; 166 if (rv == nil) rv = null; 167 [(NSMutableDictionary *)_ctx setObject:rv forKey:self->rightKey]; 168 } 169 170 if ((m = (void *)[lv methodForSelector:self->operator]) == NULL) { 171 /* no such operator method ! */ 172 [lv doesNotRecognizeSelector:self->operator]; 173 return NO; 174 } 175 176 return m(lv, self->operator, rv); 177} 178- (BOOL)evaluateWithObject:(id)_object { 179 return [self evaluateWithObject:_object inEvalContext:nil]; 180} 181 182/* NSCoding */ 183 184- (void)encodeWithCoder:(NSCoder *)_coder { 185 [_coder encodeObject:self->leftKey]; 186 [_coder encodeObject:self->rightKey]; 187 [_coder encodeValueOfObjCType:@encode(SEL) at:&(self->operator)]; 188} 189- (id)initWithCoder:(NSCoder *)_coder { 190 self->leftKey = [[_coder decodeObject] copyWithZone:[self zone]]; 191 self->rightKey = [[_coder decodeObject] copyWithZone:[self zone]]; 192 [_coder decodeValueOfObjCType:@encode(SEL) at:&(self->operator)]; 193 return self; 194} 195 196/* Comparing */ 197 198- (BOOL)isEqualToQualifier:(EOQualifier *)_qual { 199 if (![self->leftKey isEqual:[(EOKeyComparisonQualifier *)_qual leftKey]]) 200 return NO; 201 if (![self->rightKey isEqual:[(EOKeyComparisonQualifier *)_qual rightKey]]) 202 return NO; 203 if (sel_isEqual(self->operator, [(EOKeyComparisonQualifier *)_qual selector])) 204 return YES; 205 return NO; 206} 207 208/* remapping keys */ 209 210- (EOQualifier *)qualifierByApplyingTransformer:(id)_transformer 211 inContext:(id)_ctx 212{ 213 if ([_transformer respondsToSelector: 214 @selector(transformKeyComparisonQualifier:inContext:)]) { 215 return [_transformer transformKeyComparisonQualifier:self inContext:_ctx]; 216 } 217 else 218 return [[self retain] autorelease]; 219} 220 221- (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map { 222 EOKeyComparisonQualifier *kcq; 223 NSString *l, *r; 224 225 l = [_map objectForKey:self->leftKey]; 226 if (l == nil) l = self->leftKey; 227 r = [_map objectForKey:self->rightKey]; 228 if (r == nil) r = self->rightKey; 229 230 kcq = [[EOKeyComparisonQualifier alloc] 231 initWithLeftKey:l operatorSelector:self->operator rightKey:r]; 232 return [kcq autorelease]; 233} 234 235/* key/value archiving */ 236 237- (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { 238 if ((self = [super initWithKeyValueUnarchiver:_unarchiver]) != nil) { 239 NSString *s; 240 241 self->leftKey = [[_unarchiver decodeObjectForKey:@"leftKey"] retain]; 242 self->rightKey = [[_unarchiver decodeObjectForKey:@"rightKey"] retain]; 243 244 if ((s = [_unarchiver decodeObjectForKey:@"selectorName"]) != nil) { 245 if (![s hasSuffix:@":"]) s = [s stringByAppendingString:@":"]; 246 self->operator = NSSelectorFromString(s); 247 } 248 else if ((s = [_unarchiver decodeObjectForKey:@"selector"]) != nil) 249 self->operator = NSSelectorFromString(s); 250 } 251 return self; 252} 253- (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { 254 NSString *s; 255 256 [super encodeWithKeyValueArchiver:_archiver]; 257 258 [_archiver encodeObject:[self leftKey] forKey:@"leftKey"]; 259 [_archiver encodeObject:[self rightKey] forKey:@"rightKey"]; 260 261 s = NSStringFromSelector([self selector]); 262 if ([s hasSuffix:@":"]) s = [s substringToIndex:[s length] - 1]; 263 [_archiver encodeObject:s forKey:@"selectorName"]; 264} 265 266/* description */ 267 268- (NSString *)description { 269 NSMutableString *s; 270 271 s = [NSMutableString stringWithCapacity:64]; 272 [s appendString:self->leftKey]; 273 [s appendString:@" "]; 274 [s appendString:[EOQualifier stringForOperatorSelector:self->operator]]; 275 [s appendString:@" "]; 276 [s appendString:self->rightKey]; 277 return s; 278} 279 280@end /* EOKeyComparisonQualifier */ 281