]> err.no Git - sope/blob - sope-core/EOControl/EOValidation.m
improved decoding of bools
[sope] / sope-core / EOControl / EOValidation.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 "EOClassDescription.h"
23 #include "EOKeyValueCoding.h"
24 #include "EONull.h"
25 #include "common.h"
26
27 #if !LIB_FOUNDATION_LIBRARY
28
29 @interface NSException(UsedSetUI) /* does Jaguar allow -setUserInfo: ? */
30 - (void)setUserInfo:(NSDictionary *)_ui;
31 @end
32
33 #endif
34
35 @implementation NSClassDescription(EOValidation)
36
37 - (NSException *)validateObjectForDelete:(id)_object {
38   return nil;
39 }
40 - (NSException *)validateObjectForSave:(id)_object {
41   return nil;
42 }
43 - (NSException *)validateValue:(id *)_value forKey:(NSString *)_key {
44   return nil;
45 }
46
47 @end /* NSClassDescription(EOValidation) */
48
49 @implementation NSObject(EOValidation)
50
51 - (NSException *)validateForDelete {
52   return [[self classDescription] validateObjectForDelete:self];
53 }
54
55 - (NSException *)validateForInsert {
56   return [self validateForSave];
57 }
58 - (NSException *)validateForUpdate {
59   return [self validateForSave];
60 }
61
62 - (NSException *)validateForSave {
63   NSException    *e;
64   NSMutableArray *exceptions;
65   NSArray        *properties;
66   unsigned int i, count;
67   id (*validate)(id, SEL, id *, NSString *);
68   id (*objAtIdx)(id, SEL, unsigned int idx);
69   id (*valForKey)(id, SEL, NSString *);
70   
71   exceptions = nil;
72
73   /* first ask class description to validate object */
74   
75   if ((e = [[self classDescription] validateObjectForSave:self])) {
76     if (exceptions == nil) exceptions = [NSMutableArray array];
77     [exceptions addObject:e];
78   }
79   
80   /* then process all properties */
81   
82   if ((properties = [self allPropertyKeys]) == nil)
83     properties = [NSArray array];
84   
85   validate  = (void *)[self methodForSelector:@selector(validateValue:forKey:)];
86   valForKey = (void *)[self methodForSelector:@selector(valueForKey:)];
87   objAtIdx  = (void *)[properties methodForSelector:@selector(objectAtIndex:)];
88   
89   for (i = 0, count = [properties count]; i < count; i++) {
90     NSString *key;
91     id value, orgValue;
92     
93     key      = objAtIdx(properties, @selector(objectAtIndex:), i);
94     orgValue = value = valForKey(self, @selector(valueForKey:), key);
95     
96     if ((e = validate(self, @selector(validateValue:forKey:), &value, key))) {
97       /* validation of property failed */
98       if (exceptions == nil) exceptions = [NSMutableArray array];
99       [exceptions addObject:e];
100     }
101     else if (orgValue != value) {
102       /* the value was changed during validation */
103       [self takeValue:value forKey:key];
104     }
105   }
106   
107   if ((count = [exceptions count]) == 0) {
108     return nil;
109   }
110   else if (count == 1) {
111     return [exceptions objectAtIndex:0];
112   }
113   else {
114     NSException *master;
115     NSMutableDictionary *ui;
116
117     master = [exceptions objectAtIndex:0];
118     [exceptions removeObjectAtIndex:0];
119     ui = [[master userInfo] mutableCopy];
120     if (ui == nil) ui = [[NSMutableDictionary alloc] init];
121     [ui setObject:exceptions forKey:@"EOAdditionalExceptions"];
122     [master setUserInfo:ui];
123     [ui release]; ui = nil;
124     return master;
125   }
126 }
127
128 - (NSException *)validateValue:(id *)_value forKey:(NSString *)_key {
129   NSException *e;
130   
131   if ((e = [[self classDescription] validateValue:_value forKey:_key]))
132     return e;
133   
134   /* should invoke key-specific methods, eg -validateBlah: */
135   
136   {
137     /* construct 'validate'(8) + key + ':'(1) */
138     unsigned len;
139     char *buf;
140     SEL  sel;
141
142     len = [_key cStringLength];
143     buf = malloc(len + 14);
144     strcpy(buf, "validate");
145     [_key getCString:&buf[8]];
146     strcat(buf, ":");
147     buf[8] = toupper(buf[8]);
148     
149 #if NeXT_RUNTIME
150     sel = sel_getUid(buf);
151 #else
152     sel = sel_get_any_uid(buf);
153 #endif
154     if (sel) {
155       if ([self respondsToSelector:sel]) {
156         if (buf) free(buf);
157         return [self performSelector:sel withObject:*_value];
158       }
159     }
160     if (buf) free(buf);
161   }
162   return nil;
163 }
164
165 @end /* NSObject(EOValidation) */