1/* 2 Copyright (C) 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 "NSPredicate+EO.h" 23#include "EOQualifier+CoreData.h" 24#include "common.h" 25 26@implementation NSPredicate(EOCoreData) 27 28- (NSPredicate *)asPredicate { 29 return self; 30} 31- (NSExpression *)asExpression { 32 return nil; 33} 34 35@end /* NSPredicate(EOCoreData) */ 36 37 38@implementation NSCompoundPredicate(EOCoreData) 39 40- (EOQualifier *)asQualifier { 41 /* 42 Compound predicates join other predicates, they do not deal with 43 expressions. 44 */ 45 NSMutableArray *sq; 46 NSArray *sp; 47 unsigned i, count; 48 Class clazz; 49 BOOL isNot = NO; 50 EOQualifier *q; 51 52 sp = [self subpredicates]; 53 count = [sp count]; 54 55 switch ([self compoundPredicateType]) { 56 case NSNotPredicateType: 57 isNot = YES; 58 clazz = [EONotQualifier class]; 59 break; 60 case NSAndPredicateType: 61 clazz = [EOAndQualifier class]; 62 break; 63 case NSOrPredicateType: 64 clazz = [EOOrQualifier class]; 65 break; 66 default: 67 NSLog(@"ERROR(%s): unknown compound predicate type: %@", 68 __PRETTY_FUNCTION__, self); 69 return nil; 70 } 71 72 if (count == 0) 73 return [[[clazz alloc] init] autorelease]; 74 75 if (count == 1) { 76 q = [sp objectAtIndex:0]; 77 return (isNot) 78 ? [[[EONotQualifier alloc] initWithQualifier:q] autorelease] 79 : q; 80 } 81 82 sq = [[NSMutableArray alloc] initWithCapacity:count]; 83 84 for (i = 0; i < count; i++) { 85 q = [EOQualifier qualifierForPredicate:[sp objectAtIndex:i]]; 86 if (q == nil) { 87 q = [sp objectAtIndex:i]; 88 NSLog(@"ERROR(%s): could not convert predicate to qualifier: %@", 89 __PRETTY_FUNCTION__, q); 90 } 91 92 if (isNot) 93 q = [[EONotQualifier alloc] initWithQualifier:q]; 94 95 [sq addObject:q]; 96 if (isNot) [q release]; 97 98 q = nil; 99 } 100 101 q = [[(isNot ? [EOAndQualifier class] : clazz) alloc] initWithQualifier:q]; 102 [sq release]; 103 return [q autorelease]; 104} 105 106@end /* NSCompoundPredicate(EOCoreData) */ 107 108 109@implementation NSComparisonPredicate(EOCoreData) 110 111- (EOQualifier *)asQualifier { 112 NSExpression *lhs, *rhs; 113 114 lhs = [self leftExpression]; 115 rhs = [self rightExpression]; 116 117 // TODO: need to check predicate modifiers 118 // TODO: add support for variables 119 120 if ([rhs expressionType] == NSKeyPathExpressionType) { 121 if ([lhs expressionType] == NSConstantValueExpressionType) 122 return [EOKeyValueQualifier qualifierForComparisonPredicate:self]; 123 124 if ([lhs expressionType] == NSKeyPathExpressionType) 125 return [EOKeyComparisonQualifier qualifierForComparisonPredicate:self]; 126 } 127 128 NSLog(@"ERROR(%s): cannot map NSComparisonPredicate to EOQualifier: %@", 129 __PRETTY_FUNCTION__, self); 130 return (id)self; 131} 132 133/* key/value archiving */ 134 135- (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver { 136 int opt; 137 NSPredicateOperatorType ptype; 138 NSComparisonPredicateModifier mod; 139 NSExpression *left, *right; 140 NSString *selName, *s; 141 142 /* left / right - TODO: need to check 'official' keys fo rthat */ 143 144 left = [_unarchiver decodeObjectForKey:@"left"]; 145 if (left != nil && ![left isKindOfClass:[NSExpression class]]) 146 left = [NSExpression expressionForConstantValue:left]; 147 148 right = [_unarchiver decodeObjectForKey:@"right"]; 149 if (right != nil && ![right isKindOfClass:[NSExpression class]]) 150 right = [NSExpression expressionForConstantValue:right]; 151 152 /* custom selector */ 153 154 if ((selName = [_unarchiver decodeObjectForKey:@"selectorName"]) != nil) { 155 if (![selName hasSuffix:@":"]) 156 selName = [selName stringByAppendingString:@":"]; 157 } 158 else 159 selName = [_unarchiver decodeObjectForKey:@"selector"]; 160 if ([selName length] > 0) { 161 return [self initWithLeftExpression:left rightExpression:right 162 customSelector:selName ? NSSelectorFromString(selName):NULL]; 163 } 164 165 /* modifier */ 166 167 if ((s = [_unarchiver decodeObjectForKey:@"modifier"]) != nil) { 168 if ([s isEqualToString:@"direct"]) mod = NSDirectPredicateModifier; 169 else if ([s isEqualToString:@"all"]) mod = NSAllPredicateModifier; 170 else if ([s isEqualToString:@"any"]) mod = NSAnyPredicateModifier; 171 else { 172 NSLog(@"WARNING(%s): could not decode modifier (trying int): %@!", 173 __PRETTY_FUNCTION__, s); 174 mod = [s intValue]; 175 } 176 } 177 else 178 mod = NSDirectPredicateModifier; 179 180 /* type */ 181 182 if ((s = [_unarchiver decodeObjectForKey:@"type"]) != nil) { 183 if ([s isEqualToString:@"<"]) 184 ptype = NSLessThanPredicateOperatorType; 185 else if ([s isEqualToString:@"=<"]) 186 ptype = NSLessThanOrEqualToPredicateOperatorType; 187 else if ([s isEqualToString:@">"]) 188 ptype = NSGreaterThanPredicateOperatorType; 189 else if ([s isEqualToString:@">="]) 190 ptype = NSGreaterThanOrEqualToPredicateOperatorType; 191 else if ([s isEqualToString:@"=="]) 192 ptype = NSEqualToPredicateOperatorType; 193 else if ([s isEqualToString:@"!="]) 194 ptype = NSNotEqualToPredicateOperatorType; 195 else if ([s isEqualToString:@"like"]) 196 ptype = NSLikePredicateOperatorType; 197 else if ([s isEqualToString:@"contains"]) 198 ptype = NSInPredicateOperatorType; 199 else if ([s isEqualToString:@"beginswith"]) 200 ptype = NSBeginsWithPredicateOperatorType; 201 else if ([s isEqualToString:@"endswith"]) 202 ptype = NSEndsWithPredicateOperatorType; 203 else if ([s isEqualToString:@"matches"]) 204 ptype = NSMatchesPredicateOperatorType; 205 else { 206 NSLog(@"WARNING(%s): could not decode type (trying int): %@!", 207 __PRETTY_FUNCTION__, s); 208 ptype = [s intValue]; 209 } 210 } 211 else 212 ptype = NSEqualToPredicateOperatorType; 213 214 /* options */ 215 216 // TODO: use bit-compare and a set? 217 if ((s = [_unarchiver decodeObjectForKey:@"options"]) != nil) { 218 if ([s isEqualToString:@"caseInsensitive"]) 219 opt = NSCaseInsensitivePredicateOption; 220 else if ([s isEqualToString:@"diacritic"]) 221 opt = NSDiacriticInsensitivePredicateOption; 222 else { 223 NSLog(@"WARNING(%s): could not decode options (trying int): %@!", 224 __PRETTY_FUNCTION__, s); 225 opt = [s intValue]; 226 } 227 } 228 else 229 opt = 0; 230 231 /* create and return */ 232 233 return [self initWithLeftExpression:left rightExpression:right 234 modifier:mod type:ptype options:opt]; 235} 236 237- (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver { 238 NSString *s; 239 240 [_archiver encodeObject:[self leftExpression] forKey:@"left"]; 241 [_archiver encodeObject:[self rightExpression] forKey:@"right"]; 242 243 /* type */ 244 245 switch ([self predicateOperatorType]) { 246 case NSCustomSelectorPredicateOperatorType: 247 [_archiver encodeObject:NSStringFromSelector([self customSelector]) 248 forKey:@"selector"]; 249 return; /* no more info */ 250 251 case NSLessThanPredicateOperatorType: s = @"<"; break; 252 case NSLessThanOrEqualToPredicateOperatorType: s = @"=<"; break; 253 case NSGreaterThanPredicateOperatorType: s = @">"; break; 254 case NSGreaterThanOrEqualToPredicateOperatorType: s = @">="; break; 255 case NSEqualToPredicateOperatorType: s = @"=="; break; 256 case NSNotEqualToPredicateOperatorType: s = @"!="; break; 257 case NSLikePredicateOperatorType: s = @"like"; break; 258 case NSInPredicateOperatorType: s = @"contains"; break; 259 case NSBeginsWithPredicateOperatorType: s = @"beginswith"; break; 260 case NSEndsWithPredicateOperatorType: s = @"endswith"; break; 261 case NSMatchesPredicateOperatorType: s = @"matches"; break; 262 263 default: 264 s = [NSString stringWithFormat:@"%i", [self predicateOperatorType]]; 265 break; 266 } 267 if (s != nil) [_archiver encodeObject:s forKey:@"type"]; 268 269 /* modifier */ 270 271 switch ([self comparisonPredicateModifier]) { 272 case NSDirectPredicateModifier: s = nil; break; 273 case NSAllPredicateModifier: s = @"all"; break; 274 case NSAnyPredicateModifier: s = @"any"; break; 275 default: 276 s = [NSString stringWithFormat:@"%i", 277 [self comparisonPredicateModifier]]; 278 break; 279 } 280 if (s != nil) [_archiver encodeObject:s forKey:@"modifier"]; 281 282 /* options */ 283 284 // TODO: use bit-compare and a set? 285 286 if ([self options] == NSCaseInsensitivePredicateOption) 287 [_archiver encodeObject:@"caseInsensitive" forKey:@"options"]; 288 else if ([self options] == NSDiacriticInsensitivePredicateOption) 289 [_archiver encodeObject:@"diacritic" forKey:@"options"]; 290} 291 292@end /* NSComparisonPredicate(EOCoreData) */ 293