]> err.no Git - sope/blob - sope-core/EOControl/EOAndQualifier.m
added --frameworks option to configure
[sope] / sope-core / EOControl / EOAndQualifier.m
1 /*
2   Copyright (C) 2000-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 <EOControl/EOQualifier.h>
23 #include "common.h"
24
25 @interface EOQualifier(EvalContext)
26 - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx;
27 @end
28
29 @implementation EOAndQualifier
30
31 static BOOL debugEval      = NO;
32 static BOOL debugTransform = NO;
33
34 + (void)initialize {
35   debugEval = [EOQualifier isEvaluationDebuggingEnabled];
36 }
37
38 - (id)initWithQualifierArray:(NSArray *)_qualifiers {
39   self->count      = [_qualifiers count];
40   self->qualifiers = [_qualifiers copyWithZone:[self zone]];
41   return self;
42 }
43
44 - (id)initWithQualifiers:(EOQualifier *)_qual1, ... {
45   va_list     va;
46   EOQualifier *q;
47   id       *qs;
48   unsigned c;
49   NSArray  *a;
50   
51   va_start(va, _qual1);
52   for (c = 0, q = _qual1; q != nil; q = va_arg(va, id), c++)
53     ;
54   va_end(va);
55
56   if (c == 0)
57     return [self initWithQualifierArray:nil];
58
59   qs = calloc(c, sizeof(id));
60   
61   va_start(va, _qual1);
62   for (c = 0, q = _qual1; q != nil; q = va_arg(va, id), c++) {
63     qs[c] = q;
64   }
65   va_end(va);
66
67   a = [NSArray arrayWithObjects:qs count:c];
68   if (qs) free(qs);
69
70   return [self initWithQualifierArray:a];
71 }
72
73 - (void)dealloc {
74   [self->qualifiers release];
75   [super dealloc];
76 }
77
78 - (NSArray *)qualifiers {
79   return self->qualifiers;
80 }
81 - (NSArray *)subqualifiers {
82   return [self qualifiers];
83 }
84
85 /* bindings */
86
87 - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings
88   requiresAllVariables:(BOOL)_reqAll
89 {
90   NSArray  *array;
91   id       objects[self->count + 1];
92   unsigned i;
93   id (*objAtIdx)(id,SEL,unsigned);
94   
95   objAtIdx = (void *)
96     [self->qualifiers methodForSelector:@selector(objectAtIndex:)];
97   
98   for (i = 0; i < self->count; i++) {
99     id q, newq;
100
101     q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i);
102     newq = [q qualifierWithBindings:_bindings requiresAllVariables:_reqAll];
103     if (newq == nil) newq = q;
104     
105     objects[i] = newq;
106   }
107
108   array = [NSArray arrayWithObjects:objects count:self->count];
109   return [[[[self class] alloc] initWithQualifierArray:array] autorelease];
110 }
111
112 - (NSArray *)bindingKeys {
113   NSMutableSet *keys = nil;
114   unsigned i;
115   IMP objAtIdx;
116
117   objAtIdx = [self->qualifiers methodForSelector:@selector(objectAtIndex:)];
118   
119   for (i = 0; i < self->count; i++) {
120     NSArray *qb;
121     id q;
122
123     q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i);
124     qb = [q bindingKeys];
125
126     if ([qb count] > 0) {
127       if (keys == nil) keys = [NSMutableSet setWithCapacity:16];
128       [keys addObjectsFromArray:qb];
129     }
130   }
131   
132   return keys ? [keys allObjects] : [NSArray array];
133 }
134
135 /* keys */
136
137 - (void)addQualifierKeysToSet:(NSMutableSet *)_keys {
138   /* new in WO 4.5 */
139   [self->qualifiers makeObjectsPerformSelector:_cmd withObject:_keys];
140 }
141
142 /* evaluation */
143
144 - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx {
145   unsigned i;
146   IMP objAtIdx;
147   
148   if ((_ctx == nil) && (self->count > 1))
149     _ctx = [NSMutableDictionary dictionaryWithCapacity:16];
150   
151   objAtIdx = [self->qualifiers methodForSelector:@selector(objectAtIndex:)];
152   
153   for (i = 0; i < self->count; i++) {
154     id q;
155     
156     q = objAtIdx(self->qualifiers, @selector(objectAtIndex:), i);
157     
158     if (![q evaluateWithObject:_object inEvalContext:_ctx]) {
159       if (debugEval) {
160         NSLog(@"Eval: EOAndQualifier '%@':\n  qualifier[%i]: '%@'\n"
161               @"  failed on object '%@'",
162               self, i+1, q, _object);
163       }
164       return NO;
165     }
166   }
167   if (debugEval) {
168     NSLog(@"Eval: EOAndQualifier '%@':\n  true on object '%@'",
169           self, _object);
170   }
171   return YES;
172 }
173 - (BOOL)evaluateWithObject:(id)_object {
174   return [self evaluateWithObject:_object inEvalContext:nil];
175 }
176
177 /* NSCoding */
178
179 - (void)encodeWithCoder:(NSCoder *)_coder {
180   [_coder encodeObject:self->qualifiers];
181 }
182 - (id)initWithCoder:(NSCoder *)_coder {
183   self->qualifiers = [[_coder decodeObject] retain];
184   return self;
185 }
186
187 /* Comparing */
188
189 - (BOOL)isEqualToQualifier:(EOQualifier *)_qual {
190   return [self->qualifiers isEqualToArray:[(EOAndQualifier *)_qual qualifiers]];
191 }
192
193 /* remapping keys */
194
195 - (EOQualifier *)qualifierByApplyingTransformer:(id)_transformer
196   inContext:(id)_ctx
197 {
198   if ([_transformer respondsToSelector:
199                       @selector(transformAndQualifier:inContext:)]) {
200     if (debugTransform)
201       NSLog(@"transformer: %@\n  transform: %@", _transformer, self);
202     return [_transformer transformAndQualifier:self inContext:_ctx];
203   }
204   else {
205     EOAndQualifier *aq;
206     NSArray  *a;
207     id       *qs;
208     unsigned i;
209     BOOL     didTransform = NO;
210     
211     if (debugTransform) {
212       NSLog(@"EOAndQualifier: transform %i using %@ ...", 
213             self->count, _transformer);
214     }
215     
216     qs = calloc(self->count + 1, sizeof(id));
217     for (i = 0; i < self->count; i++) {
218       EOQualifier *q;
219       
220       q     = [self->qualifiers objectAtIndex:i];
221       qs[i] = [q qualifierByApplyingTransformer:_transformer inContext:_ctx];
222       if (qs[i] == nil) 
223         qs[i] = q;
224       else if (qs[i] != q) {
225         if (debugTransform)
226           NSLog(@"EOAndQualifier:   subqualifier %i did transform", i);
227         didTransform = YES;
228       }
229       else if (debugTransform)
230         NSLog(@"EOAndQualifier:   subqualifier %i did not transform", i);
231     }
232     if (didTransform) {
233       a = [[NSArray alloc] initWithObjects:qs count:self->count];
234       if (qs) free(qs);
235       aq = [[EOAndQualifier alloc] initWithQualifierArray:a];
236       [a release];
237       return [aq autorelease];
238     }
239     else {
240       if (qs) free(qs);
241       return [[self retain] autorelease];
242     }
243   }
244 }
245
246 - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map {
247   EOAndQualifier *aq;
248   NSArray  *a;
249   id       *qs;
250   unsigned i;
251   
252   qs = calloc(self->count + 1, sizeof(id));
253   for (i = 0; i < self->count; i++) {
254     EOQualifier *q;
255     
256     q     = [self->qualifiers objectAtIndex:i];
257     qs[i] = [q qualifierByApplyingKeyMap:_map];
258     if (qs[i] == nil) qs[i] = q;
259   }
260   a = [[NSArray alloc] initWithObjects:qs count:self->count];
261   if (qs) free(qs);
262   aq = [[EOAndQualifier alloc] initWithQualifierArray:a];
263   [a release];
264   return [aq autorelease];
265 }
266
267 /* key/value archiving */
268
269 - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver {
270   if ((self = [super initWithKeyValueUnarchiver:_unarchiver]) != nil) {
271     self->qualifiers = [[_unarchiver decodeObjectForKey:@"qualifiers"] copy];
272     self->count      = [self->qualifiers count];
273   }
274   return self;
275 }
276 - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
277   [super encodeWithKeyValueArchiver:_archiver];
278   [_archiver encodeObject:[self qualifiers] forKey:@"qualifiers"];
279 }
280
281 /* description */
282
283 - (NSString *)description {
284   NSMutableString *ms;
285   NSArray  *sd;
286   unsigned i, len;
287   
288   sd = [self->qualifiers valueForKey:@"qualifierDescription"];
289   if ((len = [sd count]) == 0)
290     return nil;
291   if (len == 1)
292     return [sd objectAtIndex:0];
293   
294   ms = [NSMutableString stringWithCapacity:(len * 16)];
295   [ms appendString:@"("];
296   for (i = 0; i < len; i++) {
297     if (i != 0) [ms appendString:@" AND "];
298     [ms appendString:[sd objectAtIndex:i]];
299   }
300   [ms appendString:@")"];
301   return ms;
302 }
303
304 @end /* EOAndQualifier */