Files
RestKit/Code/ObjectMapping/RKObjectPolymorphicMapping.m

141 lines
3.9 KiB
Objective-C

//
// RKDynamicObjectMapping.m
// RestKit
//
// Created by Blake Watters on 7/28/11.
// Copyright 2011 Two Toasters. All rights reserved.
//
#import "RKObjectPolymorphicMapping.h"
#import "../Support/RKLog.h"
// Set Logging Component
#undef RKLogComponent
#define RKLogComponent lcl_cRestKitObjectMapping
// Implemented in RKObjectMappingOperation
BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
@interface RKObjectPolymorphicMappingMatcher : NSObject {
NSString* _key;
id _value;
RKObjectMapping* _objectMapping;
}
@property (nonatomic, readonly) RKObjectMapping* objectMapping;
- (id)initWithKey:(NSString*)key value:(id)value objectMapping:(RKObjectMapping*)objectMapping;
- (BOOL)isMatchForData:(id)data;
- (NSString*)matchDescription;
@end
@implementation RKObjectPolymorphicMappingMatcher
@synthesize objectMapping = _objectMapping;
- (id)initWithKey:(NSString*)key value:(id)value objectMapping:(RKObjectMapping*)objectMapping {
self = [super init];
if (self) {
_key = [key retain];
_value = [value retain];
_objectMapping = [objectMapping retain];
}
return self;
}
- (void)dealloc {
[_key release];
[_value release];
[_objectMapping release];
[super dealloc];
}
- (BOOL)isMatchForData:(id)data {
return RKObjectIsValueEqualToValue([data valueForKeyPath:_key], _value);
}
- (NSString*)matchDescription {
return [NSString stringWithFormat:@"%@ == %@", _key, _value];
}
@end
///////////////////////////////////////////////////////////////////////////////////////////////////
@implementation RKObjectPolymorphicMapping
@synthesize delegate = _delegate;
@synthesize delegateBlock = _delegateBlock;
@synthesize forceCollectionMapping = _forceCollectionMapping;
+ (RKObjectPolymorphicMapping*)polymorphicMapping {
return [[self new] autorelease];
}
#if NS_BLOCKS_AVAILABLE
+ (RKObjectPolymorphicMapping*)polymorphicMappingWithBlock:(void(^)(RKObjectPolymorphicMapping*))block {
RKObjectPolymorphicMapping* mapping = [self polymorphicMapping];
block(mapping);
return mapping;
}
#endif
- (id)init {
self = [super init];
if (self) {
_matchers = [NSMutableArray new];
}
return self;
}
- (void)dealloc {
[_matchers release];
[super dealloc];
}
- (void)setObjectMapping:(RKObjectMapping*)objectMapping whenValueOfKeyPath:(NSString*)key isEqualTo:(id)value {
RKLogDebug(@"Adding dynamic object mapping for key '%@' with value '%@' to destination class: %@", key, value, NSStringFromClass(objectMapping.objectClass));
RKObjectPolymorphicMappingMatcher* matcher = [[RKObjectPolymorphicMappingMatcher alloc] initWithKey:key value:value objectMapping:objectMapping];
[_matchers addObject:matcher];
[matcher release];
}
- (RKObjectMapping*)objectMappingForDictionary:(NSDictionary*)data {
NSAssert([data isKindOfClass:[NSDictionary class]], @"Dynamic object mapping can only be performed on NSDictionary mappables, got %@", NSStringFromClass([data class]));
RKObjectMapping* mapping = nil;
RKLogTrace(@"Performing dynamic object mapping for mappable data: %@", data);
// Consult the declarative matchers first
for (RKObjectPolymorphicMappingMatcher* matcher in _matchers) {
if ([matcher isMatchForData:data]) {
RKLogTrace(@"Found declarative match for data: %@.", [matcher matchDescription]);
return matcher.objectMapping;
}
}
// Otherwise consult the delegates
if (self.delegate) {
mapping = [self.delegate objectMappingForData:data];
if (mapping) {
RKLogTrace(@"Found dynamic delegate match. Delegate = %@", self.delegate);
return mapping;
}
}
if (self.delegateBlock) {
mapping = self.delegateBlock(data);
if (mapping) {
RKLogTrace(@"Found dynamic delegateBlock match. DelegateBlock = %@", self.delegateBlock);
}
}
return mapping;
}
@end