]> err.no Git - sope/blob - sope-core/EOCoreData/NSPredicate+EO.m
4d9ecbe262cdcc4eb1d80bc51731dfcc166e79c8
[sope] / sope-core / EOCoreData / NSPredicate+EO.m
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   selName = [_unarchiver decodeObjectForKey:@"selector"];
155   if ([selName length] > 0) {
156     return [self initWithLeftExpression:left rightExpression:right
157                  customSelector:NSSelectorFromString(selName)];
158   }
159   
160   /* modifier */
161   
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;
166     else {
167       NSLog(@"WARNING(%s): could not decode modifier (trying int): %@!",
168             __PRETTY_FUNCTION__, s);
169       mod = [s intValue];
170     }
171   }
172   else
173     mod = NSDirectPredicateModifier;
174   
175   /* type */
176
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;
200     else {
201       NSLog(@"WARNING(%s): could not decode type (trying int): %@!",
202             __PRETTY_FUNCTION__, s);
203       ptype = [s intValue];
204     }
205   }
206   else
207     ptype = NSEqualToPredicateOperatorType;
208   
209   /* options */
210   
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;
217     else {
218       NSLog(@"WARNING(%s): could not decode options (trying int): %@!",
219             __PRETTY_FUNCTION__, s);
220       opt = [s intValue];
221     }
222   }
223   else
224     opt = 0;
225
226   /* create and return */
227   
228   return [self initWithLeftExpression:left rightExpression:right
229                modifier:mod type:ptype options:opt];
230 }
231
232 - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
233   NSString *s;
234   
235   [_archiver encodeObject:[self leftExpression]  forKey:@"left"];
236   [_archiver encodeObject:[self rightExpression] forKey:@"right"];
237
238   /* type */
239
240   switch ([self predicateOperatorType]) {
241   case NSCustomSelectorPredicateOperatorType:
242     [_archiver encodeObject:NSStringFromSelector([self customSelector])
243                forKey:@"selector"];
244     return; /* no more info */
245
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;
257     
258   default:
259     s = [NSString stringWithFormat:@"%i", [self predicateOperatorType]]; 
260     break;
261   }
262   if (s != nil) [_archiver encodeObject:s forKey:@"type"];
263   
264   /* modifier */
265   
266   switch ([self comparisonPredicateModifier]) {
267   case NSDirectPredicateModifier: s = nil;    break;
268   case NSAllPredicateModifier:    s = @"all"; break;
269   case NSAnyPredicateModifier:    s = @"any"; break;
270   default:
271     s = [NSString stringWithFormat:@"%i", 
272                   [self comparisonPredicateModifier]]; 
273     break;
274   }
275   if (s != nil) [_archiver encodeObject:s forKey:@"modifier"];
276   
277   /* options */
278   
279   // TODO: use bit-compare and a set?
280   
281   if ([self options] == NSCaseInsensitivePredicateOption)
282     [_archiver encodeObject:@"caseInsensitive" forKey:@"options"];
283   else if ([self options] == NSDiacriticInsensitivePredicateOption)
284     [_archiver encodeObject:@"diacritic" forKey:@"options"];
285 }
286
287 @end /* NSComparisonPredicate(EOCoreData) */