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