Document RKDynamicMappingMatcher and clean up API

This commit is contained in:
Blake Watters
2012-09-21 22:59:43 -04:00
parent 43be066e0b
commit 654364af61
8 changed files with 73 additions and 61 deletions

View File

@@ -33,7 +33,7 @@ typedef RKObjectMapping *(^RKDynamicMappingDelegateBlock)(id);
///------------------------------------
/**
A block to invoke to determine the appropriate concrete object mapping to apply to the mappable data.
Sets a block to be invoked to determine the appropriate concrete object mapping with which to map an object representation.
@param block The block object to invoke to select the object mapping with which to map the given object representation.
*/

View File

@@ -43,10 +43,10 @@
return self;
}
- (void)setObjectMapping:(RKObjectMapping *)objectMapping whenValueOfKeyPath:(NSString *)keyPath isEqualTo:(id)value
- (void)setObjectMapping:(RKObjectMapping *)objectMapping whenValueOfKeyPath:(NSString *)keyPath isEqualTo:(id)expectedValue
{
RKLogDebug(@"Adding dynamic object mapping for key '%@' with value '%@' to destination class: %@", keyPath, value, NSStringFromClass(objectMapping.objectClass));
RKDynamicMappingMatcher *matcher = [[RKDynamicMappingMatcher alloc] initWithKey:keyPath value:value objectMapping:objectMapping];
RKLogDebug(@"Adding dynamic object mapping for key '%@' with value '%@' to destination class: %@", keyPath, expectedValue, NSStringFromClass(objectMapping.objectClass));
RKDynamicMappingMatcher *matcher = [[RKDynamicMappingMatcher alloc] initWithKeyPath:keyPath expectedValue:expectedValue objectMapping:objectMapping];
[_matchers addObject:matcher];
}
@@ -59,8 +59,8 @@
// Consult the declarative matchers first
for (RKDynamicMappingMatcher *matcher in _matchers) {
if ([matcher isMatchForData:data]) {
RKLogTrace(@"Found declarative match for data: %@.", [matcher matchDescription]);
if ([matcher matches:data]) {
RKLogTrace(@"Found declarative match for matcher: %@.", matcher);
return matcher.objectMapping;
}
}

View File

@@ -9,16 +9,59 @@
#import <Foundation/Foundation.h>
#import "RKObjectMapping.h"
/**
The `RKDynamicMappingMatcher` class provides an interface for encapsulating the selection of an object mapping based on the runtime value of a property at a given key path. A matcher object is initialized with a key path, an expected value to be read from the key path, and an object mapping that is to be applied if the match evaluates to `YES`. When evaluating the match, the matcher invokes `valueForKeyPath:` on the object being matched and compares the value returned with the `expectedValue` via the `RKValueIsEqualToValue` function.
@see `RKValueIsEqualToValue()`
*/
// TODO: better name? RKKeyPathMappingMatcher | RKMappingMatcher | RKKeyPathMatcher | RKMatcher | RKValueMatcher | RKPropertyMatcher
@interface RKDynamicMappingMatcher : NSObject
@property (nonatomic, strong, readonly) RKObjectMapping *objectMapping;
@property (nonatomic, copy, readonly) NSString *primaryKeyAttribute;
///-----------------------------
/// @name Initializing a Matcher
///-----------------------------
- (id)initWithKey:(NSString *)key value:(id)value objectMapping:(RKObjectMapping *)objectMapping;
- (id)initWithKey:(NSString *)key value:(id)value primaryKeyAttribute:(NSString *)primaryKeyAttribute;
- (id)initWithPrimaryKeyAttribute:(NSString *)primaryKeyAttribute evaluationBlock:(BOOL (^)(id data))block;
- (BOOL)isMatchForData:(id)data;
- (NSString *)matchDescription;
/**
Initializes the receiver with a given key path, expected value, and an object mapping that applies in the event of a positive match.
@param keyPath The key path to obtain the comparison value from the object being matched via `valueForKeyPath:`.
@param expectedValue The value that is expected to be read from `keyPath` if there is a match.
@param objectMapping The object mapping object that applies if the comparison value is equal to the expected value.
@return The receiver, initialized with the given key path, expected value, and object mapping.
*/
- (id)initWithKeyPath:(NSString *)keyPath expectedValue:(id)expectedValue objectMapping:(RKObjectMapping *)objectMapping;
///-----------------------------
/// @name Initializing a Matcher
///-----------------------------
/**
The key path to obtain the comparison value from the object being matched via `valueForKeyPath:`.
*/
@property (nonatomic, copy, readonly) NSString *keyPath;
/**
The value that is expected to be read from `keyPath` if there is a match.
*/
@property (nonatomic, strong, readonly) id expectedValue;
/**
The object mapping object that applies if the comparison value read from `keyPath` is equal to the `expectedValue`.
*/
@property (nonatomic, strong, readonly) RKObjectMapping *objectMapping;
///-------------------------
/// @name Evaluating a Match
///-------------------------
/**
Returns a Boolean value that indicates if the given object matches the expectations of the receiver.
The match is evaluated by invoking `valueForKeyPath:` on the give object with the value of the `keyPath` property and comparing the returned value with the `expectedValue` using the `RKValueIsEqualToValue` function.
@param object The object to be evaluated.
@return `YES` if the object matches the expectations of the receiver, else `NO`.
*/
- (BOOL)matches:(id)object;
@end

View File

@@ -8,70 +8,39 @@
#import "RKDynamicMappingMatcher.h"
// Implemented in RKMappingOperation
BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
BOOL RKValueIsEqualToValue(id sourceValue, id destinationValue);
///////////////////////////////////////////////////////////////////////////////////////////////////
@interface RKDynamicMappingMatcher ()
@property (nonatomic, copy) NSString *keyPath;
@property (nonatomic, strong) id value;
@property (nonatomic, copy) BOOL (^isMatchForDataBlock)(id data);
@property (nonatomic, strong, readwrite) id expectedValue;
@property (nonatomic, strong, readwrite) RKObjectMapping *objectMapping;
@property (nonatomic, copy, readwrite) NSString *primaryKeyAttribute;
@end
@implementation RKDynamicMappingMatcher
- (id)initWithKey:(NSString *)key value:(id)value objectMapping:(RKObjectMapping *)objectMapping
- (id)initWithKeyPath:(NSString *)keyPath expectedValue:(id)expectedValue objectMapping:(RKObjectMapping *)objectMapping
{
self = [super init];
if (self) {
self.keyPath = key;
self.value = value;
self.keyPath = keyPath;
self.expectedValue = expectedValue;
self.objectMapping = objectMapping;
}
return self;
}
- (id)initWithKey:(NSString *)key value:(id)value primaryKeyAttribute:(NSString *)primaryKeyAttribute
- (BOOL)matches:(id)object
{
self = [super init];
if (self) {
self.keyPath = key;
self.value = value;
self.primaryKeyAttribute = primaryKeyAttribute;
}
return self;
return RKValueIsEqualToValue([object valueForKeyPath:self.keyPath], self.expectedValue);
}
- (id)initWithPrimaryKeyAttribute:(NSString *)primaryKeyAttribute evaluationBlock:(BOOL (^)(id data))block
- (NSString *)description
{
self = [super init];
if (self) {
self.primaryKeyAttribute = primaryKeyAttribute;
self.isMatchForDataBlock = block;
}
return self;
}
- (BOOL)isMatchForData:(id)data
{
if (self.isMatchForDataBlock) {
return self.isMatchForDataBlock(data);
}
return RKObjectIsValueEqualToValue([data valueForKeyPath:_keyPath], _value);
}
- (NSString *)matchDescription
{
if (self.isMatchForDataBlock) {
return @"No description available. Using block to perform match.";
}
return [NSString stringWithFormat:@"%@ == %@", _keyPath, _value];
return [NSString stringWithFormat:@"<%@: %p when `%@` == '%@' objectMapping: %@>", NSStringFromClass([self class]), self, self.keyPath, self.expectedValue, self.objectMapping];
}
@end

View File

@@ -35,8 +35,8 @@
#define RKLogComponent lcl_cRestKitObjectMapping
// Temporary home for object equivalancy tests
BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue);
BOOL RKObjectIsValueEqualToValue(id sourceValue, id destinationValue) {
BOOL RKValueIsEqualToValue(id sourceValue, id destinationValue);
BOOL RKValueIsEqualToValue(id sourceValue, id destinationValue) {
NSCAssert(sourceValue, @"Expected sourceValue not to be nil");
NSCAssert(destinationValue, @"Expected destinationValue not to be nil");
@@ -213,7 +213,7 @@ extern NSString * const RKObjectMappingNestingAttributeKeyName;
- (BOOL)isValue:(id)sourceValue equalToValue:(id)destinationValue
{
return RKObjectIsValueEqualToValue(sourceValue, destinationValue);
return RKValueIsEqualToValue(sourceValue, destinationValue);
}
- (BOOL)validateValue:(id *)value atKeyPath:(NSString *)keyPath