]> err.no Git - sope/blob - sope-core/EOControl/EOKeyValueQualifier.m
Xcode project
[sope] / sope-core / EOControl / EOKeyValueQualifier.m
1 /*
2   Copyright (C) 2000-2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
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 <EOControl/EONull.h>
25 #include "common.h"
26
27 @interface NSObject(QualifierDescription)
28 - (NSString *)qualifierDescription;
29 @end
30
31 @implementation EOKeyValueQualifier
32
33 static BOOL   debugEval      = NO;
34 static BOOL   debugTransform = NO;
35 static EONull *null = nil;
36
37 + (void)initialize {
38   if (null == nil)
39     null = [[EONull null] retain];
40   debugEval = [EOQualifier isEvaluationDebuggingEnabled];
41 }
42
43 - (id)initWithKey:(NSString *)_key
44   operatorSelector:(SEL)_selector
45   value:(id)_value
46 {
47   self->key      = [_key   copyWithZone:NULL];
48   self->value    = [_value retain];
49   self->operator = _selector;
50   return self;
51 }
52
53 - (void)dealloc {
54   [self->key   release];
55   [self->value release];
56   [super dealloc];
57 }
58
59 /* accessors */
60
61 - (NSString *)key {
62   return self->key;
63 }
64 - (SEL)selector {
65   return self->operator;
66 }
67 - (id)value {
68   return self->value;
69 }
70
71 /* bindings */
72
73 - (EOQualifier *)qualifierWithBindings:(NSDictionary *)_bindings
74   requiresAllVariables:(BOOL)_reqAll
75 {
76   static Class VarClass = Nil;
77   NSString *newKey;
78   id       newValue;
79   BOOL     needNew;
80   
81   if (VarClass == Nil) VarClass = [EOQualifierVariable class];
82   needNew = NO;
83
84   if ([self->key class] == VarClass) {
85     newKey = [_bindings objectForKey:[(EOQualifierVariable *)self->key key]];
86     if (newKey == nil) {
87       if (_reqAll)
88         // throw exception
89         ;
90       else
91         newKey = self->key;
92     }
93     else
94       needNew = YES;
95   }
96   else
97     newKey = self->key;
98
99   if ([self->value class] == VarClass) {
100     newValue = [_bindings objectForKey:[self->value key]];
101     if (newValue == nil) {
102       if (_reqAll)
103         // throw exception
104         ;
105       else
106         newValue = self->value;
107     }
108     else
109       needNew = YES;
110   }
111   else
112     newValue = self->value;
113
114   if (!needNew)
115     return self;
116
117   return [[[[self class] alloc]
118                          initWithKey:newKey
119                          operatorSelector:self->operator
120                          value:newValue] autorelease];
121 }
122
123 - (NSArray *)bindingKeys {
124   static Class VarClass = Nil;
125   Class keyClass, vClass;
126   if (VarClass == Nil) VarClass = [EOQualifierVariable class];
127   
128   keyClass = [self->key   class];
129   vClass   = [self->value class];
130   
131   if ((keyClass == VarClass) && (vClass == VarClass)) {
132     id o[2];
133     o[0] = [(EOQualifierVariable *)self->key   key];
134     o[1] = [(EOQualifierVariable *)self->value key];
135     return [NSArray arrayWithObjects:o count:2];
136   }
137   
138   if (keyClass == VarClass)
139     return [NSArray arrayWithObject:[(EOQualifierVariable *)self->key key]];
140   if (vClass == VarClass)
141     return [NSArray arrayWithObject:[(EOQualifierVariable *)self->value key]];
142   
143   return [NSArray array];
144 }
145
146 /* keys */
147
148 - (void)addQualifierKeysToSet:(NSMutableSet *)_keys {
149   /* new in WO 4.5 */
150   [_keys addObject:self->key];
151 }
152
153 /* evaluation */
154
155 - (BOOL)evaluateWithObject:(id)_object inEvalContext:(id)_ctx {
156   id   lv, rv;
157   BOOL (*m)(id, SEL, id);
158   BOOL result;
159   
160   if (_ctx == nil)
161     _ctx = [NSMutableDictionary dictionaryWithCapacity:16];
162   
163   if ((lv = [(NSDictionary *)_ctx objectForKey:self->key]) == nil) {
164     lv = [_object valueForKeyPath:self->key];
165     if (lv == nil) lv = null;
166     [(NSMutableDictionary *)_ctx setObject:lv forKey:self->key];
167   }
168   
169   rv = self->value ? self->value : null;
170   
171   if (debugEval) {
172     NSLog(@"Eval: EOKeyValueQualifier:(%@ %@)\n"
173           @"  compare %@<%@>\n  with %@<%@>",
174           self->key, NSStringFromSelector(self->operator),
175           lv, NSStringFromClass([lv class]),
176           rv, NSStringFromClass([rv class]));
177   }
178   
179   if ((m = (void *)[lv methodForSelector:self->operator]) == NULL) {
180     /* no such operator method ! */
181     [lv doesNotRecognizeSelector:self->operator];
182     return NO;
183   }
184   
185   result = m(lv, self->operator, rv);
186   if (debugEval)
187     NSLog(@"  %@", result ? @"MATCHES" : @"DOES NOT MATCH");
188   return result;
189 }
190 - (BOOL)evaluateWithObject:(id)_object {
191   return [self evaluateWithObject:_object inEvalContext:nil];
192 }
193
194 /* NSCoding */
195
196 - (void)encodeWithCoder:(NSCoder *)_coder {
197   [_coder encodeObject:self->key];
198   [_coder encodeObject:self->value];
199   [_coder encodeValueOfObjCType:@encode(SEL) at:&(self->operator)];
200 }
201 - (id)initWithCoder:(NSCoder *)_coder {
202   self->key   = [[_coder decodeObject] copyWithZone:[self zone]];
203   self->value = [[_coder decodeObject] retain];
204   [_coder decodeValueOfObjCType:@encode(SEL) at:&(self->operator)];
205   return self;
206 }
207
208 /* Comparing */
209
210 - (BOOL)isEqualToQualifier:(EOQualifier *)_qual {
211   if (![self->key isEqual:[(EOKeyValueQualifier *)_qual key]])
212     return NO;
213   if (![self->value isEqual:[(EOKeyValueQualifier *)_qual value]])
214     return NO;
215   if (sel_eq(self->operator, [(EOKeyValueQualifier *)_qual selector]))
216     return YES;
217   return NO;
218 }
219
220 /* remapping keys */
221
222 - (EOQualifier *)qualifierByApplyingTransformer:(id)_transformer
223   inContext:(id)_ctx
224 {
225   if ([_transformer respondsToSelector:
226                       @selector(transformKeyValueQualifier:inContext:)]) {
227     if (debugTransform)
228       NSLog(@"transformer: %@\n  transform: %@", _transformer, self);
229     return [_transformer transformKeyValueQualifier:self inContext:_ctx];
230   }
231   else {
232     if (debugTransform)
233       NSLog(@"EOKeyValueQualifier: not transforming using %@", _transformer);
234     return [[self retain] autorelease];
235   }
236 }
237
238 - (EOQualifier *)qualifierByApplyingKeyMap:(NSDictionary *)_map {
239   EOKeyValueQualifier *kvq;
240   NSString *k;
241   
242   k = [_map objectForKey:self->key];
243   if (k == nil) k = self->key;
244   
245   kvq = [[EOKeyValueQualifier alloc] 
246           initWithKey:k operatorSelector:self->operator value:self->value];
247   return [kvq autorelease];
248 }
249
250 /* description */
251
252 - (NSString *)description {
253   NSMutableString *s;
254   
255   s = [NSMutableString stringWithCapacity:64];
256   [s appendString:self->key];
257   [s appendString:@" "];
258   [s appendString:[EOQualifier stringForOperatorSelector:self->operator]];
259   [s appendString:@" "];
260   [s appendString:[self->value qualifierDescription]];
261   return s;
262 }
263
264 @end /* EOKeyValueQualifier */