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 sel = sel_registerName(buf); 150 if (sel) { 151 if ([self respondsToSelector:sel]) { 152 if (buf) free(buf); 153 return [self performSelector:sel withObject:*_value]; 154 } 155 } 156 if (buf) free(buf); 157 } 158 return nil; 159} 160 161@end /* NSObject(EOValidation) */ 162