2 Copyright (C) 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 "NSPredicate+EO.h"
23 #include "EOQualifier+CoreData.h"
26 @implementation NSPredicate(EOCoreData)
28 - (NSPredicate *)asPredicate {
31 - (NSExpression *)asExpression {
35 @end /* NSPredicate(EOCoreData) */
38 @implementation NSCompoundPredicate(EOCoreData)
40 - (EOQualifier *)asQualifier {
42 Compound predicates join other predicates, they do not deal with
52 sp = [self subpredicates];
55 switch ([self compoundPredicateType]) {
56 case NSNotPredicateType:
58 clazz = [EONotQualifier class];
60 case NSAndPredicateType:
61 clazz = [EOAndQualifier class];
63 case NSOrPredicateType:
64 clazz = [EOOrQualifier class];
67 NSLog(@"ERROR(%s): unknown compound predicate type: %@",
68 __PRETTY_FUNCTION__, self);
73 return [[[clazz alloc] init] autorelease];
76 q = [sp objectAtIndex:0];
78 ? [[[EONotQualifier alloc] initWithQualifier:q] autorelease]
82 sq = [[NSMutableArray alloc] initWithCapacity:count];
84 for (i = 0; i < count; i++) {
85 q = [EOQualifier qualifierForPredicate:[sp objectAtIndex:i]];
87 q = [sp objectAtIndex:i];
88 NSLog(@"ERROR(%s): could not convert predicate to qualifier: %@",
89 __PRETTY_FUNCTION__, q);
93 q = [[EONotQualifier alloc] initWithQualifier:q];
96 if (isNot) [q release];
101 q = [[(isNot ? [EOAndQualifier class] : clazz) alloc] initWithQualifier:q];
103 return [q autorelease];
106 @end /* NSCompoundPredicate(EOCoreData) */
109 @implementation NSComparisonPredicate(EOCoreData)
111 - (EOQualifier *)asQualifier {
112 NSExpression *lhs, *rhs;
114 lhs = [self leftExpression];
115 rhs = [self rightExpression];
117 // TODO: need to check predicate modifiers
118 // TODO: add support for variables
120 if ([rhs expressionType] == NSKeyPathExpressionType) {
121 if ([lhs expressionType] == NSConstantValueExpressionType)
122 return [EOKeyValueQualifier qualifierForComparisonPredicate:self];
124 if ([lhs expressionType] == NSKeyPathExpressionType)
125 return [EOKeyComparisonQualifier qualifierForComparisonPredicate:self];
128 NSLog(@"ERROR(%s): cannot map NSComparisonPredicate to EOQualifier: %@",
129 __PRETTY_FUNCTION__, self);
133 /* key/value archiving */
135 - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver {
137 NSPredicateOperatorType ptype;
138 NSComparisonPredicateModifier mod;
139 NSExpression *left, *right;
140 NSString *selName, *s;
142 /* left / right - TODO: need to check 'official' keys fo rthat */
144 left = [_unarchiver decodeObjectForKey:@"left"];
145 if (left != nil && ![left isKindOfClass:[NSExpression class]])
146 left = [NSExpression expressionForConstantValue:left];
148 right = [_unarchiver decodeObjectForKey:@"right"];
149 if (right != nil && ![right isKindOfClass:[NSExpression class]])
150 right = [NSExpression expressionForConstantValue:right];
152 /* custom selector */
154 selName = [_unarchiver decodeObjectForKey:@"selector"];
155 if ([selName length] > 0) {
156 return [self initWithLeftExpression:left rightExpression:right
157 customSelector:NSSelectorFromString(selName)];
162 if ((s = [_unarchiver decodeObjectForKey:@"modifier"]) != nil) {
163 if ([s isEqualToString:@"direct"]) mod = NSDirectPredicateModifier;
164 else if ([s isEqualToString:@"all"]) mod = NSAllPredicateModifier;
165 else if ([s isEqualToString:@"any"]) mod = NSAnyPredicateModifier;
167 NSLog(@"WARNING(%s): could not decode modifier (trying int): %@!",
168 __PRETTY_FUNCTION__, s);
173 mod = NSDirectPredicateModifier;
177 if ((s = [_unarchiver decodeObjectForKey:@"type"]) != nil) {
178 if ([s isEqualToString:@"<"])
179 ptype = NSLessThanPredicateOperatorType;
180 else if ([s isEqualToString:@"=<"])
181 ptype = NSLessThanOrEqualToPredicateOperatorType;
182 else if ([s isEqualToString:@">"])
183 ptype = NSGreaterThanPredicateOperatorType;
184 else if ([s isEqualToString:@">="])
185 ptype = NSGreaterThanOrEqualToPredicateOperatorType;
186 else if ([s isEqualToString:@"=="])
187 ptype = NSEqualToPredicateOperatorType;
188 else if ([s isEqualToString:@"!="])
189 ptype = NSNotEqualToPredicateOperatorType;
190 else if ([s isEqualToString:@"like"])
191 ptype = NSLikePredicateOperatorType;
192 else if ([s isEqualToString:@"contains"])
193 ptype = NSInPredicateOperatorType;
194 else if ([s isEqualToString:@"beginswith"])
195 ptype = NSBeginsWithPredicateOperatorType;
196 else if ([s isEqualToString:@"endswith"])
197 ptype = NSEndsWithPredicateOperatorType;
198 else if ([s isEqualToString:@"matches"])
199 ptype = NSMatchesPredicateOperatorType;
201 NSLog(@"WARNING(%s): could not decode type (trying int): %@!",
202 __PRETTY_FUNCTION__, s);
203 ptype = [s intValue];
207 ptype = NSEqualToPredicateOperatorType;
211 // TODO: use bit-compare and a set?
212 if ((s = [_unarchiver decodeObjectForKey:@"options"]) != nil) {
213 if ([s isEqualToString:@"caseInsensitive"])
214 opt = NSCaseInsensitivePredicateOption;
215 else if ([s isEqualToString:@"diacritic"])
216 opt = NSDiacriticInsensitivePredicateOption;
218 NSLog(@"WARNING(%s): could not decode options (trying int): %@!",
219 __PRETTY_FUNCTION__, s);
226 /* create and return */
228 return [self initWithLeftExpression:left rightExpression:right
229 modifier:mod type:ptype options:opt];
232 - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
235 [_archiver encodeObject:[self leftExpression] forKey:@"left"];
236 [_archiver encodeObject:[self rightExpression] forKey:@"right"];
240 switch ([self predicateOperatorType]) {
241 case NSCustomSelectorPredicateOperatorType:
242 [_archiver encodeObject:NSStringFromSelector([self customSelector])
244 return; /* no more info */
246 case NSLessThanPredicateOperatorType: s = @"<"; break;
247 case NSLessThanOrEqualToPredicateOperatorType: s = @"=<"; break;
248 case NSGreaterThanPredicateOperatorType: s = @">"; break;
249 case NSGreaterThanOrEqualToPredicateOperatorType: s = @">="; break;
250 case NSEqualToPredicateOperatorType: s = @"=="; break;
251 case NSNotEqualToPredicateOperatorType: s = @"!="; break;
252 case NSLikePredicateOperatorType: s = @"like"; break;
253 case NSInPredicateOperatorType: s = @"contains"; break;
254 case NSBeginsWithPredicateOperatorType: s = @"beginswith"; break;
255 case NSEndsWithPredicateOperatorType: s = @"endswith"; break;
256 case NSMatchesPredicateOperatorType: s = @"matches"; break;
259 s = [NSString stringWithFormat:@"%i", [self predicateOperatorType]];
262 if (s != nil) [_archiver encodeObject:s forKey:@"type"];
266 switch ([self comparisonPredicateModifier]) {
267 case NSDirectPredicateModifier: s = nil; break;
268 case NSAllPredicateModifier: s = @"all"; break;
269 case NSAnyPredicateModifier: s = @"any"; break;
271 s = [NSString stringWithFormat:@"%i",
272 [self comparisonPredicateModifier]];
275 if (s != nil) [_archiver encodeObject:s forKey:@"modifier"];
279 // TODO: use bit-compare and a set?
281 if ([self options] == NSCaseInsensitivePredicateOption)
282 [_archiver encodeObject:@"caseInsensitive" forKey:@"options"];
283 else if ([self options] == NSDiacriticInsensitivePredicateOption)
284 [_archiver encodeObject:@"diacritic" forKey:@"options"];
287 @end /* NSComparisonPredicate(EOCoreData) */