1// ADRecord.m (this is -*- ObjC -*-) 2// 3// \author: Bj�rn Giesler <giesler@ira.uka.de> 4// 5// Address Book Framework for GNUstep 6// 7 8#import "ADAddressBook.h" 9#import "ADGlobals.h" 10#import "ADConverter.h" 11#import "ADMultiValue.h" 12#import "ADRecord.h" 13 14@implementation ADRecord 15- init 16{ 17 _dict = nil; 18 _book = nil; 19 _readOnly = NO; 20 21 if([self isKindOfClass: [ADPerson class]]) 22 [self setValue: @"Person" forProperty: @"Type"]; 23 else if([self isKindOfClass: [ADGroup class]]) 24 [self setValue: @"Group" forProperty: @"Type"]; 25 26 return [super init]; 27} 28 29- (void) dealloc 30{ 31 [_dict release]; 32 [_book release]; 33 [super dealloc]; 34} 35 36- (id) valueForProperty: (NSString *) property 37{ 38 return [_dict objectForKey: property]; 39} 40 41- (BOOL) setValue: (id) value 42 forProperty: (NSString *) property 43{ 44 NSMutableDictionary *newDict; 45 46 if(_readOnly) 47 { 48 NSLog(@"Trying to set value %@ for property %@ in read-only record %@\n", 49 value, property, [self uniqueId]); 50 return NO; 51 } 52 53 newDict = [NSMutableDictionary dictionaryWithDictionary: _dict]; 54 55 if(!value || [value isEqual: @""]) 56 [newDict removeObjectForKey: property]; 57 else 58 [newDict setObject: value forKey: property]; 59 60 [_dict release]; 61 _dict = [[NSDictionary alloc] initWithDictionary: newDict]; 62 63 if([property isEqualToString: ADModificationDateProperty]) 64 return NO; 65 66 [self setValue: [NSDate date] forProperty: ADModificationDateProperty]; 67 68 if(![property isEqualToString: ADUIDProperty]) 69 [[NSNotificationCenter defaultCenter] 70 postNotificationName: ADRecordChangedNotification 71 object: self 72 userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 73 value, ADChangedValueKey, 74 property, ADChangedPropertyKey, 75 nil]]; 76 77 return YES; 78} 79 80- (BOOL) removeValueForProperty: (NSString*) property 81{ 82 NSMutableDictionary *newDict; 83 84 if(_readOnly) 85 { 86 NSLog(@"Trying to remove value for property %@ in read-only record %@\n", 87 property, [self uniqueId]); 88 return NO; 89 } 90 91 newDict = [NSMutableDictionary dictionaryWithDictionary: _dict]; 92 [newDict removeObjectForKey: property]; 93 [_dict release]; 94 _dict = [[NSDictionary alloc] initWithDictionary: newDict]; 95 96 if(![property isEqualToString: ADUIDProperty]) 97 [[NSNotificationCenter defaultCenter] 98 postNotificationName: ADRecordChangedNotification 99 object: self 100 userInfo: [NSDictionary dictionaryWithObjectsAndKeys: 101 property, ADChangedPropertyKey, 102 nil]]; 103 return YES; 104} 105 106- (ADAddressBook*) addressBook 107{ 108 return _book; 109} 110 111- (void) setAddressBook: (ADAddressBook*) book 112{ 113 if(_book) 114 [NSException raise: ADAddressBookConsistencyError 115 format: @"Cannot set address book on record '%@'" 116 @" (already has one)", [self uniqueId]]; 117 if(!book) 118 [NSException raise: ADAddressBookConsistencyError 119 format: @"Cannot set nil address book on record '%@'", 120 [self uniqueId]]; 121 _book = [book retain]; 122} 123 124- (id) copyWithZone: (NSZone*) z 125{ 126 ADRecord* obj = NSCopyObject(self, 0, z); 127 obj->_readOnly = _readOnly; 128 129 // delete UID if it has one 130 if([_dict objectForKey: ADUIDProperty]) 131 { 132 NSMutableDictionary *d = 133 [NSMutableDictionary 134 dictionaryWithDictionary: [_dict copy]]; 135 [d removeObjectForKey: ADUIDProperty]; 136 obj->_dict = [[NSDictionary alloc] initWithDictionary: d]; 137 } 138 else 139 obj->_dict = [_dict copy]; 140 141 obj->_book = nil; 142 143 return obj; 144} 145@end 146 147@implementation ADRecord(ADRecord_Convenience) 148- (NSString*) uniqueId 149{ 150 return [self valueForProperty: ADUIDProperty]; 151} 152@end 153 154@implementation ADRecord(AddressesExtensions) 155- (BOOL) readOnly 156{ 157 return _readOnly; 158} 159 160- (void) setReadOnly 161{ 162 _readOnly = YES; 163} 164 165- (id) initWithRepresentation: (NSString*) str 166 type: (NSString*) type 167{ 168 id<ADInputConverting> converter; id obj; 169 Class c; 170 171 c = [self class]; 172 [self release]; 173 174 converter = [[ADConverterManager sharedManager] 175 inputConverterForType: type]; 176 if(!converter) return nil; 177 178 if(![converter useString: str]) 179 return nil; 180 181 obj = [converter nextRecord]; 182 if(!obj) return nil; 183 184 if(![[obj class] isSubclassOfClass: c]) 185 { 186 NSLog(@"It's of %@, not %@\n", [c className], [obj className]); 187 return nil; 188 } 189 190 return [obj retain]; 191} 192 193- (NSString*) representationWithType: (NSString*) type 194{ 195 id<ADOutputConverting> converter; 196 197 [self release]; 198 199 converter = [[ADConverterManager sharedManager] 200 outputConverterForType: type]; 201 [converter storeRecord: self]; 202 return [converter string]; 203} 204 205- (NSDictionary*) contentDictionary 206{ 207 NSMutableDictionary *dict; 208 NSEnumerator *e; 209 NSString *key; 210 211 dict = [NSMutableDictionary dictionaryWithCapacity: [_dict count]]; 212 e = [[_dict allKeys] objectEnumerator]; 213 while((key = [e nextObject])) 214 { 215 NSObject *obj = [_dict objectForKey: key]; 216 if([obj isKindOfClass: [ADMultiValue class]]) 217 [dict setObject: [(ADMultiValue*)obj contentArray] forKey: key]; 218 else if([obj isKindOfClass: [NSString class]] || 219 [obj isKindOfClass: [NSData class]] || 220 [obj isKindOfClass: [NSDate class]] || 221 [obj isKindOfClass: [NSArray class]] || 222 [obj isKindOfClass: [NSDictionary class]]) 223 [dict setObject: obj forKey: key]; 224 else 225 NSLog(@"Value for \"%@\" in record \"%@\" has invalid class %@\n", 226 key, [self uniqueId], [obj className]); 227 } 228 229 return dict; 230} 231@end 232