]> err.no Git - sope/blob - sope-core/NGExtensions/NGRuleEngine.subproj/NGRuleModel.m
bumped framework versions
[sope] / sope-core / NGExtensions / NGRuleEngine.subproj / NGRuleModel.m
1 /*
2   Copyright (C) 2003-2004 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 "NGRuleModel.h"
23 #include "NGRule.h"
24 #include "NGRuleParser.h"
25 #include "EOTrueQualifier.h"
26 #include <NGExtensions/NSObject+Logs.h>
27 #include <EOControl/EOControl.h>
28 #include "common.h"
29
30 // TODO: add a candidate cache
31
32 @implementation NGRuleModel
33
34 + (id)ruleModelWithPropertyList:(id)_plist {
35   static NGRuleParser *ruleParser = nil; // THREAD
36
37   if (ruleParser == nil)
38     ruleParser = [[NGRuleParser sharedRuleParser] retain];
39   
40   return [ruleParser parseRuleModelFromPropertyList:_plist];
41 }
42 + (id)ruleModelWithContentsOfUserDefault:(NSString *)_defName {
43   id plist;
44   
45   plist = [[NSUserDefaults standardUserDefaults] objectForKey:_defName];
46   if (plist == nil) return nil;
47   
48   return [self ruleModelWithPropertyList:plist];
49 }
50
51 - (id)init {
52   if ((self = [super init])) {
53     self->rules = [[NSMutableArray alloc] initWithCapacity:16];
54   }
55   return self;
56 }
57 - (id)initWithRules:(NSArray *)_rules {
58   if ((self = [self init])) {
59     [self->rules addObjectsFromArray:_rules];
60   }
61   return self;
62 }
63
64 - (id)initWithPropertyList:(id)_plist {
65   [self autorelease];
66   return [[[self class] ruleModelWithPropertyList:_plist] retain];
67 }
68
69 - (id)initWithContentsOfFile:(NSString *)_path {
70   NSString *s;
71   id plist;
72   
73   if ((s = [[NSString alloc] initWithContentsOfFile:_path])) {
74     [self release];
75     return nil;
76   }
77   plist = [s propertyList];
78   [s release];
79   return [self initWithPropertyList:plist];
80 }
81
82 - (id)initWithContentsOfUserDefault:(NSString *)_defName {
83   [self autorelease];
84   return [[[self class] ruleModelWithContentsOfUserDefault:_defName] retain];
85 }
86
87 - (id)initWithKeyValueArchiveAtURL:(NSURL *)_url {
88   EOKeyValueUnarchiver *unarchiver;
89   NSDictionary *plist;
90   
91   if ((plist = [NSDictionary dictionaryWithContentsOfURL:_url]) == nil) {
92     [self errorWithFormat:@"Could not read plist at URL: %@", _url];
93     [self release];
94     return nil;
95   }
96   
97   unarchiver = [[EOKeyValueUnarchiver alloc] initWithDictionary:plist];
98   self = [self initWithKeyValueUnarchiver:unarchiver];
99   [unarchiver release]; unarchiver = nil;
100   
101   return self;
102 }
103
104 - (void)dealloc {
105   [self->rules release];
106   [super dealloc];
107 }
108
109 /* accessors */
110
111 - (void)setRules:(NSArray *)_rules {
112   [self->rules removeAllObjects];
113   if (_rules != nil) [self->rules addObjectsFromArray:_rules];
114 }
115 - (NSArray *)rules {
116   return [[self->rules shallowCopy] autorelease];
117 }
118
119 - (void)addRule:(NGRule *)_rule {
120   if (_rule == nil) return;
121   [self->rules addObject:_rule];
122 }
123 - (void)removeRule:(NGRule *)_rule {
124   if (_rule == nil) return;
125   [self->rules removeObject:_rule];
126 }
127
128 - (void)addRules:(NSArray *)_rules {
129   if (_rules != nil) [self->rules addObjectsFromArray:_rules];
130 }
131
132 /* operations */
133
134 static int candidateSort(NGRule *rule1, NGRule *rule2, NGRuleModel *model) {
135   static Class TrueQualClass = Nil;
136   EOQualifier *q1, *q2;
137   register int pri1, pri2;
138   
139   pri1 = [rule1 priority];
140   pri2 = [rule2 priority];
141   if (pri1 != pri2)
142     return pri1 > pri2 ? NSOrderedAscending : NSOrderedDescending;
143   
144   /* check number of qualifiers (order on how specific the qualifier is) */
145
146   if (TrueQualClass == Nil) TrueQualClass = [EOTrueQualifier class];
147   q1 = [rule1 qualifier];
148   q2 = [rule2 qualifier];
149   
150   pri1 = [q1 isKindOfClass:TrueQualClass]
151     ? - 1
152     : ([q1 respondsToSelector:@selector(count)] ? [q1 count] : 0);
153   pri2 = [q2 isKindOfClass:TrueQualClass]
154     ? -1
155     : ([q2 respondsToSelector:@selector(count)] ? [q2 count] : 0);
156   
157   if (pri1 != pri2)
158     return pri1 > pri2 ? NSOrderedAscending : NSOrderedDescending;
159   
160   return NSOrderedSame;
161 }
162
163 - (NSArray *)candidateRulesForKey:(NSString *)_key {
164   NSMutableArray *candidates;
165   unsigned i, cnt;
166   
167   /* first, find all candidates */
168   candidates = nil;
169   cnt = [self->rules count];
170   for (i = 0; i < cnt; i++) {
171     NGRule *rule;
172     
173     rule = [self->rules objectAtIndex:i];
174     if ([rule isCandidateForKey:_key]) {
175       if (candidates == nil)
176         candidates = [[NSMutableArray alloc] initWithCapacity:cnt];
177       [candidates addObject:rule];
178     }
179   }
180
181   /* sort candidates */
182   [candidates sortUsingFunction:(void *)candidateSort context:self];
183   
184   return candidates;
185 }
186
187 /* representations */
188
189 /* key/value archiving */
190
191 - (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver {
192   return [self initWithRules:[_unarchiver decodeObjectForKey:@"rules"]];
193 }
194 - (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
195   [_archiver encodeObject:[self rules] forKey:@"rules"];
196 }
197
198 @end /* NGRuleModel */