API  0.9.6
 All Classes Files Functions Variables Macros Groups Pages
CPCompoundPredicate.j
Go to the documentation of this file.
1 /*
2  * CPCompoundPredicate.j
3  *
4  * Portions based on NSCompoundPredicate.m in Cocotron (http://www.cocotron.org/)
5  * Copyright (c) 2006-2007 Christopher J. W. Lloyd
6  *
7  * Created by cacaodev.
8  * Copyright 2010.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  */
24 
25 
44 
46 
56 @implementation CPCompoundPredicate : CPPredicate
57 {
59  CPArray _predicates;
60 }
61 
62 // Constructors
68 - (id)initWithType:(CPCompoundPredicateType)type subpredicates:(CPArray)predicates
69 {
70  self = [super init];
71 
72  if (self)
73  {
74  _type = type;
75  _predicates = predicates;
76  }
77 
78  return self;
79 }
80 
86 + (CPPredicate)notPredicateWithSubpredicate:(CPPredicate)predicate
87 {
88  return [[self alloc] initWithType:CPNotPredicateType subpredicates:[CPArray arrayWithObject:predicate]];
89 }
90 
96 + (CPPredicate)andPredicateWithSubpredicates:(CPArray)subpredicates
97 {
98  return [[self alloc] initWithType:CPAndPredicateType subpredicates:subpredicates];
99 }
100 
106 + (CPPredicate)orPredicateWithSubpredicates:(CPArray)predicates
107 {
108  return [[self alloc] initWithType:CPOrPredicateType subpredicates:predicates];
109 }
110 
111 // Getting Information About a Compound Predicate
116 - (CPCompoundPredicateType)compoundPredicateType
117 {
118  return _type;
119 }
120 
125 - (CPArray)subpredicates
126 {
127  return _predicates;
128 }
129 
130 - (CPPredicate)predicateWithSubstitutionVariables:(CPDictionary)variables
131 {
132  var subp = [CPArray array],
133  count = [subp count],
134  i = 0;
135 
136  for (; i < count; i++)
137  {
138  var p = [subp objectAtIndex:i],
139  sp = [p predicateWithSubstitutionVariables:variables];
140 
141  [subp addObject:sp];
142  }
143 
144  return [[CPCompoundPredicate alloc] initWithType:_type subpredicates:subp];
145 }
146 
147 - (CPString)predicateFormat
148 {
149  var result = "",
150  args = [CPArray array],
151  count = [_predicates count],
152  i = 0;
153 
154  if (count == 0)
155  return @"TRUEPREDICATE";
156 
157  for (; i < count; i++)
158  {
159  var subpredicate = [_predicates objectAtIndex:i],
160  precedence = [subpredicate predicateFormat];
161 
162  if ([subpredicate isKindOfClass:[CPCompoundPredicate class]] && [[subpredicate subpredicates] count]> 1 && [subpredicate compoundPredicateType] != _type)
163  precedence = [CPString stringWithFormat:@"(%s)",precedence];
164 
165  if (precedence != nil)
166  [args addObject:precedence];
167  }
168 
169  switch (_type)
170  {
171  case CPNotPredicateType: result += "NOT " + [args objectAtIndex:0];
172  break;
173 
174  case CPAndPredicateType: result += [args objectAtIndex:0];
175  var count = [args count];
176  for (var j = 1; j < count; j++)
177  result += " AND " + [args objectAtIndex:j];
178  break;
179 
180  case CPOrPredicateType: result += [args objectAtIndex:0];
181  var count = [args count];
182  for (var j = 1; j < count; j++)
183  result += " OR " + [args objectAtIndex:j];
184  break;
185  }
186 
187  return result;
188 }
189 
190 - (BOOL)evaluateWithObject:(id)object
191 {
192  return [self evaluateWithObject:object substitutionVariables:nil];
193 }
194 
195 - (BOOL)evaluateWithObject:(id)object substitutionVariables:(CPDictionary)variables
196 {
197  var result = NO,
198  count = [_predicates count],
199  i = 0;
200 
201  if (count == 0)
202  return YES;
203 
204  for (; i < count; i++)
205  {
206  var predicate = [_predicates objectAtIndex:i];
207 
208  switch (_type)
209  {
210  case CPNotPredicateType: return ![predicate evaluateWithObject:object substitutionVariables:variables];
211 
212  case CPAndPredicateType: if (i == 0)
213  result = [predicate evaluateWithObject:object substitutionVariables:variables];
214  else
215  result = result && [predicate evaluateWithObject:object substitutionVariables:variables];
216  if (!result)
217  return NO;
218  break;
219 
220  case CPOrPredicateType: if ([predicate evaluateWithObject:object substitutionVariables:variables])
221  return YES;
222  break;
223  }
224  }
225 
226  return result;
227 }
228 
229 - (BOOL)isEqual:(id)anObject
230 {
231  if (self === anObject)
232  return YES;
233 
234  if (anObject.isa !== self.isa || _type !== [anObject compoundPredicateType] || ![_predicates isEqualToArray:[anObject subpredicates]])
235  return NO;
236 
237  return YES;
238 }
239 
240 @end
241 
243 
244 - (id)initWithCoder:(CPCoder)coder
245 {
246  self = [super init];
247  if (self != nil)
248  {
249  _predicates = [coder decodeObjectForKey:@"CPCompoundPredicateSubpredicates"];
250  _type = [coder decodeIntForKey:@"CPCompoundPredicateType"];
251  }
252 
253  return self;
254 }
255 
256 - (void)encodeWithCoder:(CPCoder)coder
257 {
258  [coder encodeObject:_predicates forKey:@"CPCompoundPredicateSubpredicates"];
259  [coder encodeInt:_type forKey:@"CPCompoundPredicateType"];
260 }
261 
262 @end