]> err.no Git - sope/blob - sope-core/NGExtensions/NGRuleEngine.subproj/NGRuleContext.m
Drop apache 1 build-dependency
[sope] / sope-core / NGExtensions / NGRuleEngine.subproj / NGRuleContext.m
1 /*
2   Copyright (C) 2003-2006 SKYRIX Software AG
3   Copyright (C) 2006      Helge Hess
4
5   This file is part of SOPE.
6
7   SOPE is free software; you can redistribute it and/or modify it under
8   the terms of the GNU Lesser General Public License as published by the
9   Free Software Foundation; either version 2, or (at your option) any
10   later version.
11
12   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
13   WARRANTY; without even the implied warranty of MERCHANTABILITY or
14   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15   License for more details.
16
17   You should have received a copy of the GNU Lesser General Public
18   License along with SOPE; see the file COPYING.  If not, write to the
19   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20   02111-1307, USA.
21 */
22
23 #include "NGRuleContext.h"
24 #include "NGRule.h"
25 #include "NGRuleModel.h"
26 #include "NSObject+Logs.h"
27 #include "common.h"
28 #import <EOControl/EOQualifier.h>
29
30 @implementation NGRuleContext
31
32 + (id)ruleContextWithModelInUserDefault:(NSString *)_defName {
33   NGRuleModel *mod;
34   
35   if ((mod = [NGRuleModel ruleModelWithContentsOfUserDefault:_defName]) == nil)
36     return nil;
37   
38   return [self ruleContextWithModel:mod];
39 }
40
41 + (id)ruleContextWithModel:(NGRuleModel *)_model {
42   return [[[self alloc] initWithModel:_model] autorelease];
43 }
44
45 - (id)initWithModel:(NGRuleModel *)_model {
46   if ((self = [super init])) {
47     [self setModel:_model];
48   }
49   return self;
50 }
51 - (id)init {
52   return [self initWithModel:nil];
53 }
54
55 - (void)dealloc {
56   [self->model        release];
57   [self->storedValues release];
58   [super dealloc];
59 }
60
61 /* accessors */
62
63 - (void)setModel:(NGRuleModel *)_model {
64   ASSIGN(self->model, _model);
65 }
66 - (NGRuleModel *)model {
67   return self->model;
68 }
69
70 /* values */
71
72 - (void)takeStoredValue:(id)_value forKey:(NSString *)_key {
73   if (_value) {
74     if (self->storedValues == nil)
75       self->storedValues = [[NSMutableDictionary alloc] initWithCapacity:32];
76     [self->storedValues setObject:_value forKey:_key];
77   }
78   else
79     [self->storedValues removeObjectForKey:_key];
80 }
81 - (id)storedValueForKey:(NSString *)_key {
82   return [self->storedValues objectForKey:_key];
83 }
84
85 - (void)takeValue:(id)_value forKey:(NSString *)_key {
86   [self takeStoredValue:_value forKey:_key];
87 }
88
89 - (void)reset {
90   [self->storedValues removeAllObjects];
91 }
92
93 /* processing */
94
95 - (id)inferredValueForKey:(NSString *)_key {
96   NSArray  *rules;
97   unsigned i, count;
98   
99   if (self->debugOn)
100     [self debugWithFormat:@"calculate value for key: '%@'", _key];
101   
102   /* select candidates */
103   rules = [[self model] candidateRulesForKey:_key];
104   if (self->debugOn)
105     [self debugWithFormat:@"  candidate rules: %@", rules];
106   
107   /* check qualifiers */
108   for (i = 0, count = [rules count]; i < count; i++) {
109     NGRule *rule;
110     
111     rule = [rules objectAtIndex:i];
112     if ([(id<EOQualifierEvaluation>)[rule qualifier] evaluateWithObject:self]){
113       if (self->debugOn)
114         [self debugWithFormat:@"  rule %i matches: %@", i, rule];
115       return [[rule action] fireInContext:self];
116     }
117   }
118   if (self->debugOn)
119     [self debugWithFormat:@"  no rule matched !"];
120   return nil;
121 }
122
123 - (NSArray *)allPossibleValuesForKey:(NSString *)_key {
124   NSMutableArray *values;
125   NSArray  *rules;
126   unsigned i, count;
127   
128   if (self->debugOn)
129     [self debugWithFormat:@"calculate all values for key: '%@'", _key];
130   
131   /* select candidates */
132   rules = [[self model] candidateRulesForKey:_key];
133   if (self->debugOn)
134     [self debugWithFormat:@"  candidate rules: %@", rules];
135   
136   values = [NSMutableArray arrayWithCapacity:16];
137   
138   /* check qualifiers */
139   for (i = 0, count = [rules count]; i < count; i++) {
140     NGRule *rule;
141     
142     rule = [rules objectAtIndex:i];
143     if ([(id<EOQualifierEvaluation>)[rule qualifier] evaluateWithObject:self]){
144       id v;
145       
146       if (self->debugOn)
147         [self debugWithFormat:@"  rule %i matches: %@", i, rule];
148       
149       v = [[rule action] fireInContext:self];
150       [values addObject:(v != nil ? v : (id)[NSNull null])];
151     }
152   }
153   if (self->debugOn)
154     [self debugWithFormat:@"  %d rules matched.", [values count]];
155   return values;
156 }
157
158 - (id)valueForKey:(NSString *)_key {
159   id v;
160
161   // TODO: add rule cache?
162   
163   /* look for constants */
164   if ((v = [self->storedValues objectForKey:_key]) != nil)
165     return v;
166   
167   /* look into rule system */
168   if ((v = [self inferredValueForKey:_key]) != nil)
169     return v;
170   
171   return nil;
172 }
173
174 - (NSArray *)valuesForKeyPath:(NSString *)_kp
175   takingSuccessiveValues:(NSArray *)_values
176   forKeyPath:(NSString *)_valkp
177 {
178   NSMutableArray *results;
179   unsigned i, count;
180   
181   count   = [_values count];
182   results = [NSMutableArray arrayWithCapacity:count];
183   
184   for (i = 0; i < count; i++) {
185     id ruleValue;
186     
187     /* take the value */
188     [self takeValue:[_values objectAtIndex:i] forKeyPath:_valkp];
189
190     /* calculate the rule value */
191     ruleValue = [self valueForKeyPath:_kp];
192     [results addObject:(ruleValue != nil ? ruleValue : (id)[NSNull null])];
193   }
194   return results;
195 }
196
197 /* debugging */
198
199 - (BOOL)isDebuggingEnabled {
200   return self->debugOn;
201 }
202 - (void)setDebugEnabled:(BOOL)_flag {
203   self->debugOn = _flag;
204 }
205
206 @end /* NGRuleContext */