API  0.9.7
 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 
27 
37 @implementation CPCompoundPredicate : CPPredicate
38 {
40  CPArray _predicates;
41 }
42 
43 // Constructors
49 - (id)initWithType:(CPCompoundPredicateType)type subpredicates:(CPArray)predicates
50 {
51  self = [super init];
52 
53  if (self)
54  {
55  _type = type;
56  _predicates = predicates;
57  }
58 
59  return self;
60 }
61 
67 + (CPPredicate)notPredicateWithSubpredicate:(CPPredicate)predicate
68 {
69  return [[self alloc] initWithType:CPNotPredicateType subpredicates:[CPArray arrayWithObject:predicate]];
70 }
71 
77 + (CPPredicate)andPredicateWithSubpredicates:(CPArray)subpredicates
78 {
79  return [[self alloc] initWithType:CPAndPredicateType subpredicates:subpredicates];
80 }
81 
87 + (CPPredicate)orPredicateWithSubpredicates:(CPArray)predicates
88 {
89  return [[self alloc] initWithType:CPOrPredicateType subpredicates:predicates];
90 }
91 
92 // Getting Information About a Compound Predicate
97 - (CPCompoundPredicateType)compoundPredicateType
98 {
99  return _type;
100 }
101 
106 - (CPArray)subpredicates
107 {
108  return _predicates;
109 }
110 
111 - (CPPredicate)predicateWithSubstitutionVariables:(CPDictionary)variables
112 {
113  var subp = [CPArray array],
114  count = [subp count],
115  i = 0;
116 
117  for (; i < count; i++)
118  {
119  var p = [subp objectAtIndex:i],
120  sp = [p predicateWithSubstitutionVariables:variables];
121 
122  [subp addObject:sp];
123  }
124 
125  return [[CPCompoundPredicate alloc] initWithType:_type subpredicates:subp];
126 }
127 
128 - (CPString)predicateFormat
129 {
130  var result = "",
131  args = [CPArray array],
132  count = [_predicates count],
133  i = 0;
134 
135  if (count == 0)
136  return @"TRUEPREDICATE";
137 
138  for (; i < count; i++)
139  {
140  var subpredicate = [_predicates objectAtIndex:i],
141  precedence = [subpredicate predicateFormat];
142 
143  if ([subpredicate isKindOfClass:[CPCompoundPredicate class]] && [[subpredicate subpredicates] count]> 1 && [subpredicate compoundPredicateType] != _type)
144  precedence = [CPString stringWithFormat:@"(%s)",precedence];
145 
146  if (precedence != nil)
147  [args addObject:precedence];
148  }
149 
150  switch (_type)
151  {
152  case CPNotPredicateType: result += "NOT " + [args objectAtIndex:0];
153  break;
154 
155  case CPAndPredicateType: result += [args objectAtIndex:0];
156  var count = [args count];
157  for (var j = 1; j < count; j++)
158  result += " AND " + [args objectAtIndex:j];
159  break;
160 
161  case CPOrPredicateType: result += [args objectAtIndex:0];
162  var count = [args count];
163  for (var j = 1; j < count; j++)
164  result += " OR " + [args objectAtIndex:j];
165  break;
166  }
167 
168  return result;
169 }
170 
171 - (BOOL)evaluateWithObject:(id)object
172 {
173  return [self evaluateWithObject:object substitutionVariables:nil];
174 }
175 
176 - (BOOL)evaluateWithObject:(id)object substitutionVariables:(CPDictionary)variables
177 {
178  var result = NO,
179  count = [_predicates count],
180  i = 0;
181 
182  if (count == 0)
183  return YES;
184 
185  for (; i < count; i++)
186  {
187  var predicate = [_predicates objectAtIndex:i];
188 
189  switch (_type)
190  {
191  case CPNotPredicateType: return ![predicate evaluateWithObject:object substitutionVariables:variables];
192 
193  case CPAndPredicateType: if (i == 0)
194  result = [predicate evaluateWithObject:object substitutionVariables:variables];
195  else
196  result = result && [predicate evaluateWithObject:object substitutionVariables:variables];
197  if (!result)
198  return NO;
199  break;
200 
201  case CPOrPredicateType: if ([predicate evaluateWithObject:object substitutionVariables:variables])
202  return YES;
203  break;
204  }
205  }
206 
207  return result;
208 }
209 
210 - (BOOL)isEqual:(id)anObject
211 {
212  if (self === anObject)
213  return YES;
214 
215  if (anObject === nil || anObject.isa !== self.isa || _type !== [anObject compoundPredicateType] || ![_predicates isEqualToArray:[anObject subpredicates]])
216  return NO;
217 
218  return YES;
219 }
220 
221 @end
222 
224 
225 - (id)initWithCoder:(CPCoder)coder
226 {
227  self = [super init];
228  if (self != nil)
229  {
230  _predicates = [coder decodeObjectForKey:@"CPCompoundPredicateSubpredicates"];
231  _type = [coder decodeIntForKey:@"CPCompoundPredicateType"];
232  }
233 
234  return self;
235 }
236 
237 - (void)encodeWithCoder:(CPCoder)coder
238 {
239  [coder encodeObject:_predicates forKey:@"CPCompoundPredicateSubpredicates"];
240  [coder encodeInt:_type forKey:@"CPCompoundPredicateType"];
241 }
242 
243 @end